--- title: "Modification and querying" description: "Subscription endpoints fall into two groups." source: "https://docs.tokenz.one/en/v2/subscriptions/modification" api_version: "v2" locale: "en" version_status: "current" docs_stage: "prod" --- # Modification and querying Subscription endpoints fall into two groups. **Direct query and modification.** These calls do not use a Checkout Session. Use them to display a subscription, its order history and invoice links, and open plan changes, and to cancel a subscription or a pending plan change when the action comes from you. Direct cancellation takes effect immediately. - [List subscriptions](https://docs.tokenz.one/en/v2/subscriptions/modification#list-subscriptions) and [Retrieve a subscription](https://docs.tokenz.one/en/v2/subscriptions/modification#retrieve-a-subscription) — show the subscription. - [List orders of a subscription](https://docs.tokenz.one/en/v2/subscriptions/modification#list-orders-of-a-subscription) and [Invoice links](https://docs.tokenz.one/en/v2/subscriptions/modification#invoice-links) — show order history and invoices. - [List plan changes](https://docs.tokenz.one/en/v2/subscriptions/modification#list-plan-changes) — show open plan changes. - [Cancel a subscription](https://docs.tokenz.one/en/v2/subscriptions/modification#cancel-a-subscription) and [Cancel a plan change](https://docs.tokenz.one/en/v2/subscriptions/modification#cancel-a-plan-change) — cancel the subscription or a pending change from your side. **Requests the consumer confirms.** These calls return a Checkout Session. Redirect the consumer to its `url`. The subscription does not change until they confirm. Use them when the change needs the consumer's action or consent: they asked to cancel, they must approve a plan change, or they must supply a new payment method. - [Request consumer cancellation](https://docs.tokenz.one/en/v2/subscriptions/modification#request-consumer-cancellation) — cancel because the consumer asked to. - [Request a plan change](https://docs.tokenz.one/en/v2/subscriptions/modification#request-a-plan-change) — the consumer approves a new plan. - [Request a payment-method change](https://docs.tokenz.one/en/v2/subscriptions/modification#request-a-payment-method-change) — the consumer supplies a new card. **Amount format:** Monetary values (such as `amount` fields) are expressed in the smallest minor unit of each currency. See [Supported currencies](https://docs.tokenz.one/en/v2/checkout/currency). Results are limited to the API key's merchant and test mode. ## List subscriptions `GET /v2/subscription` returns subscriptions for the authenticated merchant, newest id first. `reference` and `customerId` are exact matches and combine with AND. `limit` is 1–100 and defaults to 20. Omit `cursor` for the first page; pass `pagination.nextCursor` back unchanged as `cursor` for the next page. ```bash curl --request GET \ --url 'https://api.tokenz.one/v2/subscription?customerId=customer_123&limit=20' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "data": [ { "id": "subscription_1p4LS47fB1h_t", "object": "subscription", "status": "active", "test": true, "reference": "Pro Plan (Monthly)", "customerId": "customer_123", "items": [ { "id": "item_1p4LS47fB1i_t", "detail": { "product": { "price": { "amount": 1000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Monthly)", "images": ["https://example.com/pro-plan.png"] } } } ], "interval": { "unit": "MONTH", "count": 1 }, "provideAccess": true, "currentBillingPeriodEnd": "2026-08-01T00:00:00Z", "createdAt": "2026-07-01T00:00:00Z", "updatedAt": "2026-07-01T00:00:00Z" } ], "pagination": { "nextCursor": "subscription_1p4LC47fB2a_t" } } ``` `pagination.nextCursor` is absent on the last page. ## Retrieve a subscription `GET /v2/subscription/{id}` returns one subscription. The call fails with `404` when the id is unknown, belongs to another merchant, or does not match the API key's test mode. ```bash curl --request GET \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "id": "subscription_1p4LS47fB1h_t", "object": "subscription", "status": "active", "test": true, "reference": "Pro Plan (Monthly)", "customerId": "customer_123", "items": [ { "id": "item_1p4LS47fB1i_t", "detail": { "product": { "price": { "amount": 1000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Monthly)", "images": ["https://example.com/pro-plan.png"] } } } ], "interval": { "unit": "MONTH", "count": 1 }, "provideAccess": true, "currentBillingPeriodEnd": "2026-08-01T00:00:00Z", "createdAt": "2026-07-01T00:00:00Z", "updatedAt": "2026-07-01T00:00:00Z" } ``` ## Cancel a subscription `POST /v2/subscription/{id}/cancel` cancels the subscription immediately. There is no request body. The subscription must be `trialing`, `active`, or `unpaid` to be canceled. Already `canceled` subscription are unaffected and other statuses result in `422` with code `subscription.status-invalid`. Cancellation sets `canceledAt`, stops future renewal orders, and sends `subscription.canceled`. It is final. See [Lifecycle & billing](https://docs.tokenz.one/en/v2/subscriptions/lifecycle#cancellation) for what happens to access and in-flight orders. ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/cancel \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "id": "subscription_1p4LS47fB1h_t", "object": "subscription", "status": "canceled", "test": true, "items": [ { "id": "item_1p4LS47fB1i_t", "detail": { "product": { "price": { "amount": 1000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Monthly)", "images": ["https://example.com/pro-plan.png"] } } } ], "interval": { "unit": "MONTH", "count": 1 }, "provideAccess": true, "provideAccessUntil": "2026-08-01T00:00:00Z", "canceledAt": "2026-07-15T12:00:00Z", "createdAt": "2026-07-01T00:00:00Z", "updatedAt": "2026-07-15T12:00:00Z" } ``` ## Request consumer cancellation `POST /v2/subscription/{id}/request/cancel` does not cancel the subscription itself. It creates a Checkout Session the consumer uses to confirm. Redirect them to the returned `url`. After they confirm, the subscription is canceled the same way as a direct cancellation, including the `subscription.canceled` webhook. Required body fields: - `successUrl`: where the consumer lands after confirming. - `pendingUrl`: where the consumer lands if confirmation is still pending. - `cancelUrl`: where the consumer lands if they abandon the flow. `theme` is optional (`LIGHT` or `DARK`). ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/cancel \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \ --data '{ "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel" }' ``` ### Response `201` returns the Checkout Session. The subscription stays in its current status until the consumer confirms. ```json { "id": "checkoutsession_1p4LC47fB2a_t", "object": "checkoutsession", "url": "https://checkout.tokenz.one/1p4LC47fB2a_t", "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel", "test": true, "subscription": { "id": "subscription_1p4LS47fB1h_t", "object": "subscription", "status": "active" }, "createdAt": "2026-07-15T12:00:00Z", "updatedAt": "2026-07-15T12:00:00Z" } ``` ## Request a payment-method change `POST /v2/subscription/{id}/request/payment-method-change` creates a Checkout Session where the consumer supplies a new card. Redirect them to `url`. Consent for the new card is captured on that hosted page; see [Payment methods & consent](https://docs.tokenz.one/en/v2/subscriptions/payment-methods). The body is the same three redirect URLs as consumer cancellation (`successUrl`, `pendingUrl`, `cancelUrl`), plus optional `theme`. When the subscription is `unpaid`, the returned session is the checkout for the outstanding order. Paying that order replaces the payment method and reactivates the subscription. On success, Tokenz sends `subscription.activated` webhook. For an `active` or `trialing` subscription a Checkout Session for payment method update is returned. On success, Tokenz sends `subscription.payment_method_updated` webhook. ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/payment-method-change \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \ --data '{ "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel" }' ``` ### Response ```json { "id": "checkoutsession_1p4LP47fB3b_t", "object": "checkoutsession", "url": "https://checkout.tokenz.one/1p4LP47fB3b_t", "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel", "test": true, "subscription": { "id": "subscription_1p4LS47fB1h_t", "object": "subscription", "status": "active" }, "createdAt": "2026-07-15T12:00:00Z", "updatedAt": "2026-07-15T12:00:00Z" } ``` ## Request a plan change `POST /v2/subscription/{id}/request/plan-change` asks the consumer to approve a new item and billing interval. The change is not applied until they approve it on the returned Checkout Session. The subscription must be active or trialing, other states result in `422` with code `subscription.status-invalid`. The body must include `itemDetails`, `replacementMode`, `successUrl`, `pendingUrl`, and `cancelUrl`. `itemDetails` replaces the subscription's current item: exactly one non-discounted item with `quantity` of 1. The item's currency must match the subscription's currency, otherwise error `400` with code `currency.inconsistent` is returned. `interval` sets the new billing interval, `{ "unit": "WEEK" | "MONTH" | "YEAR", "count": }`. `successUrl` is used after an immediate change is applied, and `pendingUrl` is used after a deferred change is approved. `replacementMode`: - `IMMEDIATE_PRORATION`: for a time-based subscription (for example a premium plan), apply the change as soon as the consumer authorizes the order. When subscription is active the consumer is credited the remaining prorated value of the current billing period and the billing anchor is set to the date of the authorization. When subscription is trialing the trial ends immediately with no additional credit and the subscription starts with the new plan. If the calculated credit exceeds the new item's price, error `422` with code `subscription.plan-replacement-invalid` is returned. Do not use this mode for an item-based subscription (for example a monthly currency purchase). Contact Tokenz if you want upgrade options for an item-based subscription. - `DEFERRED`: apply the change after the current billing period ends. Approval sends `subscription.plan_change_scheduled`; the plan itself changes when the order for next billing period is paid. When the plan is applied (immediately or at the next period), Tokenz sends `subscription.plan_changed` webhook. ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/request/plan-change \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' \ --data '{ "itemDetails": [{ "product": { "price": { "amount": 2000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Yearly)", "images": ["https://example.com/pro-plan.png"], "taxCategory": "SAAS" } }], "interval": { "unit": "YEAR", "count": 1 }, "replacementMode": "DEFERRED", "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel" }' ``` Use `"replacementMode": "IMMEDIATE_PRORATION"` to apply the same plan as soon as the consumer approves it. Use this mode for a time-based subscription, not an item-based one. ### Response `201` returns the Checkout Session and the pending change. ```json { "id": "checkoutsession_1p4LR47fB4c_t", "object": "checkoutsession", "url": "https://checkout.tokenz.one/1p4LR47fB4c_t", "successUrl": "https://example.com/success", "pendingUrl": "https://example.com/pending", "cancelUrl": "https://example.com/cancel", "test": true, "subscriptionChange": { "id": "subscriptionchange_1p4LC9aB2cD_t", "object": "subscriptionchange", "status": "pending", "replacementMode": "DEFERRED", "interval": { "unit": "YEAR", "count": 1 }, "items": [ { "id": "item_1p4LS47fB1j_t", "detail": { "product": { "price": { "amount": 2000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Yearly)", "images": ["https://example.com/pro-plan.png"] } } } ] }, "createdAt": "2026-07-15T12:00:00Z", "updatedAt": "2026-07-15T12:00:00Z" } ``` Redirect the consumer to `url`. Store `subscriptionChange.id` if you need to list or cancel the change later. ## List plan changes `GET /v2/subscription/{id}/plan-change` returns the subscription's open changes: those in `pending` or `approved` status. `canceled` and `applied` changes are not included. A change moves through `pending` (waiting for the consumer), `approved` (accepted, and for a deferred change not yet applied), `applied`, or `canceled`. ```bash curl --request GET \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "data": [ { "id": "subscriptionchange_1p4LC9aB2cD_t", "object": "subscriptionchange", "status": "approved", "replacementMode": "DEFERRED", "interval": { "unit": "YEAR", "count": 1 }, "items": [ { "id": "item_1p4LS47fB1j_t", "detail": { "product": { "price": { "amount": 2000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Yearly)", "images": ["https://example.com/pro-plan.png"] } } } ] } ] } ``` ## Cancel a plan change `POST /v2/subscription/{id}/plan-change/{changeId}/cancel` cancels a `pending` or `approved` change before it is applied. There is no request body. Canceling an `applied`, `expired` or `canceled` change returns `422` with `subscription.change-status-invalid`. Deferred changes become non-cancelable when an order for next billing period is created even if their status is still `approved`, attempt to cancel such a change returns `422` with `subscription.change-status-invalid`. A deferred change that was already approved sends `subscription.plan_change_canceled`. ```bash curl --request POST \ --url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change/subscriptionchange_1p4LC9aB2cD_t/cancel \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "id": "subscriptionchange_1p4LC9aB2cD_t", "object": "subscriptionchange", "status": "canceled", "replacementMode": "DEFERRED", "interval": { "unit": "YEAR", "count": 1 }, "items": [ { "id": "item_1p4LS47fB1j_t", "detail": { "product": { "price": { "amount": 2000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Yearly)", "images": ["https://example.com/pro-plan.png"] } } } ] } ``` ## List orders of a subscription `GET /v2/order` on the Order service lists the orders created for one subscription. `subscriptionId` is required. `limit` (1–100, default 20) and `cursor` page the same way as [List subscriptions](https://docs.tokenz.one/en/v2/subscriptions/modification#list-subscriptions): pass `pagination.nextCursor` back unchanged as `cursor`. Orders are newest id first, and only those matching the API key's test mode are returned. Each order includes `subscriptionId`. Items may include `billedPeriodStart` (inclusive) and `billedPeriodEnd` (exclusive) for the period that order covers. ```bash curl --request GET \ --url 'https://api.tokenz.one/v2/order?subscriptionId=subscription_1p4LS47fB1h_t&limit=20' \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "data": [ { "id": "order_1D5xA9BnKfv_t", "object": "order", "status": "succeeded", "test": true, "subscriptionId": "subscription_1p4LS47fB1h_t", "amount": { "amount": 1000, "currency": "USD" }, "items": [ { "id": "item_1p4LO47fB1k_t", "billedPeriodStart": "2026-07-01T00:00:00Z", "billedPeriodEnd": "2026-08-01T00:00:00Z", "detail": { "product": { "price": { "amount": 1000, "currency": "USD" }, "quantity": 1, "label": "Pro Plan (Monthly)", "images": ["https://example.com/pro-plan.png"] } } } ], "createdAt": "2026-07-01T00:00:00Z", "updatedAt": "2026-07-01T00:00:05Z" } ], "pagination": { "nextCursor": "order_1p4LC47fB2a_t" } } ``` ## Invoice links `GET /v2/order/{id}/invoice` returns the buyer's hosted invoice links for an order, including a subscription renewal. `displayUrl` is the hosted invoice page. `downloadUrl` is the PDF and is present only after the PDF has been generated. Redirect the customer to the full URL including the fragment part with Tokenz generated signature. ```bash curl --request GET \ --url https://api.tokenz.one/v2/order/order_1D5xA9BnKfv_t/invoice \ --header 'Authorization: Bearer secret_test_YOUR_KEY_HERE' ``` ### Response ```json { "displayUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t#generated-invoice-signature", "downloadUrl": "https://invoice.tokenz.one/i/1D5xA9BnKfv_t/download#generated-invoice-signature" } ``` Until the PDF exists, the response contains `displayUrl` only. ## Webhooks Keep your own records in sync from webhooks rather than polling these endpoints. The events for the operations on this page: - `subscription.canceled` — direct cancellation, or a consumer-confirmed cancellation, completed. - `subscription.payment_method_updated` — the consumer confirmed a new card. - `subscription.plan_change_scheduled` — the consumer approved a deferred plan change. - `subscription.plan_change_canceled` — a scheduled deferred plan change was canceled before it was applied. - `subscription.plan_changed` — an immediate or deferred plan change was applied. `items` and `interval` in the payload are the new plan. Payload shapes are in [Webhooks](https://docs.tokenz.one/en/v2/subscriptions/webhooks).