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 and Retrieve a subscription — show the subscription.
- List orders of a subscription and Invoice links — show order history and invoices.
- List plan changes — show open plan changes.
- Cancel a subscription and 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 — cancel because the consumer asked to.
- Request a plan change — the consumer approves a new plan.
- 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.
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.
curl --request GET \
--url 'https://api.tokenz.one/v2/subscription?customerId=customer_123&limit=20' \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
Response
{
"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.
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
Response
{
"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 for what happens to access and in-flight orders.
curl --request POST \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/cancel \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
Response
{
"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).
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.
{
"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.
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.
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
{
"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": <integer ≥ 1> }. 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, error422with codesubscription.plan-replacement-invalidis 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 sendssubscription.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.
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.
{
"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.
curl --request GET \
--url https://api.tokenz.one/v2/subscription/subscription_1p4LS47fB1h_t/plan-change \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
Response
{
"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.
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
{
"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: 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.
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
{
"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.
curl --request GET \
--url https://api.tokenz.one/v2/order/order_1D5xA9BnKfv_t/invoice \
--header 'Authorization: Bearer secret_test_YOUR_KEY_HERE'
Response
{
"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.itemsandintervalin the payload are the new plan.
Payload shapes are in Webhooks.