Skip to content

Get a price migration

The subscriptions.migrations.get operation: GET /api/v1/subscriptions/migrations/{id} in the REST API and the subscriptions_migrations_get tool in the MCP server.

GET/api/v1/subscriptions/migrations/{id}

Returns a price migration with its progress: how many subscriptions matched and were scheduled, how many customers were notified, how many changes were applied at a renewal and how many are still pending, and how many were skipped (at once, or dropped later because the subscription was canceled or changed again). status is completed once no change is pending.

At a glance

  • REST: GET /api/v1/subscriptions/migrations/{id}
  • MCP tool: subscriptions_migrations_get
  • Operation ID: subscriptions.migrations.get
  • Scope: Brand
  • Permission: subscriptions:read
  • Risk tier: read
  • Dry run: Not supported
  • Idempotency: Not needed (read only)
  • Modes: Test and live
  • Authentication: API key with the subscriptions:read scope
  • Since: M5

Request

Path parameters

FieldTypeDescription
idsmig_… ID

Query parameters

This operation takes no query parameters.

Response

200 OK with a JSON object:

FieldTypeDescription
idsmig_… ID
object"subscription_migration"
livemodeboolean
brandIdbrd_… ID
fromPriceIdprice_… ID
toPriceIdprice_… ID
currencystring
effectiveone of next_renewal, date
effectiveDatedate-time or null
noticeDaysinteger
filterobject
filter.statusesarray of one of incomplete, incomplete_expired, trialing, active, past_due, unpaid, paused, canceled
filter.customerIdsarray of cus_… ID or null
statusone of scheduled, completedscheduled while changes are still waiting for their renewal; completed once none is.
countsobjectProgress (spec §16.14).
counts.matchedinteger (at least 0)Subscriptions on the old price that the filter matched.
counts.scheduledinteger (at least 0)Of those, the ones given the change.
counts.notifiedinteger (at least 0)Customers sent their notice.
counts.appliedinteger (at least 0)Changes applied at a renewal.
counts.pendinginteger (at least 0)Changes still waiting for their renewal.
counts.skippedinteger (at least 0)Matched but not changed: skipped at once (skippedAtCreation), or dropped before their renewal because the subscription was canceled or changed again.
skippedAtCreationobjectWhy matching subscriptions weren't changed: pending_update (another change was already waiting), cancel_scheduled (set to end at its period end).
revenueobjectThe monthly recurring amount of the changed items before and after (licensed items; metered items are billed from usage).
revenue.mrrBeforemoney
revenue.mrrAftermoney
revenue.mrrDeltamoney
firstChangeAtdate-time or nullThe first scheduled change.
lastChangeAtdate-time or nullThe last scheduled change.
versioninteger
createdAtdate-time
updatedAtdate-time

Examples

A migration half applied

HTTP
GET /api/v1/subscriptions/migrations/smig_01jacq4m3xf0v8w9zq2y7k5n6h
Authorization: Bearer or_test_…

Response (200):

JSON
{
  "id": "smig_01jacq4m3xf0v8w9zq2y7k5n6h",
  "object": "subscription_migration",
  "livemode": false,
  "brandId": "brd_01jacq4m3xf0v8w9zq2y7k5n6b",
  "fromPriceId": "price_01jacq4m3xf0v8w9zq2y7k5n6p",
  "toPriceId": "price_01jacq4m3xf0v8w9zq2y7k5n6q",
  "currency": "EUR",
  "effective": "next_renewal",
  "effectiveDate": null,
  "noticeDays": 30,
  "filter": {
    "statuses": ["trialing", "active", "past_due"],
    "customerIds": null
  },
  "status": "scheduled",
  "counts": {
    "matched": 42,
    "scheduled": 40,
    "notified": 40,
    "applied": 25,
    "pending": 14,
    "skipped": 3
  },
  "skippedAtCreation": {
    "pending_update": 2,
    "cancel_scheduled": 0
  },
  "revenue": {
    "mrrBefore": {
      "amount": "400000000",
      "currency": "EUR"
    },
    "mrrAfter": {
      "amount": "480000000",
      "currency": "EUR"
    },
    "mrrDelta": {
      "amount": "80000000",
      "currency": "EUR"
    }
  },
  "firstChangeAt": "2026-11-20T10:00:00.000Z",
  "lastChangeAt": "2026-12-19T10:00:00.000Z",
  "version": 67,
  "createdAt": "2026-10-20T09:00:00.000Z",
  "updatedAt": "2026-12-05T10:00:00.000Z"
}

Errors

CodeHTTP statusWhenWhat to do
resource_not_found404No price migration with this ID exists for the brand in this mode.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
permission_denied403The credentials can't read this brand's subscriptions.Ask an organization owner or admin for a role or scope that allows this action.

It can also return these common errors: validation_failed, api_version_unsupported, authentication_required, api_key_invalid, scope_required, dry_run_not_supported, rate_limited, internal_error.