Customer Portal subscriptions

Let a customer view and manage their own subscriptions in the portal — see plans, switch plans, add a card during dunning, and cancel.

These endpoints let a signed-in customer manage their own subscriptions: list them, open one, see which plans it can switch to, add a card while a renewal is failing (dunning), and cancel.

Actions here are constrained by the merchant's portal config — a merchant chooses whether customers may switch plans or cancel on their own. Everything is scoped to the customer that owns the session; a customer can never see another's subscriptions.

These endpoints power the Customer Portal — the self-service surface your end customers use, under your brand. They are authenticated by a portal session cookie, established through the magic-link flow (request a link, then verify the token), not by an API key. See Sessions & config.

The subscription object

Returned by the list and retrieve endpoints on this page.

FieldTypeDescription
idstring
statusstringOne of trialing, active, dunning, paused, cancelled, expired.
current_offer_idstring
billing_cyclestringOne of daily, biweekly, monthly, quarterly, half_yearly, yearly, custom, none.
currencystring
current_amountnumberCurrent amount in minor units.
current_period_startstring | null(ISO 8601 UTC).
current_period_endstring | null(ISO 8601 UTC).
next_billing_atstring | null(ISO 8601 UTC).
cancel_at_period_endboolean
cancelled_atstring | null(ISO 8601 UTC).
cycles_completednumberNumber of completed billing cycles.
cycle_limitnumber | nullMax charges; null = ongoing.
trial_startstring | null(ISO 8601 UTC).
trial_endstring | null(ISO 8601 UTC).
preferred_installmentsnumber
dunning_next_retry_atstring | nullNext dunning retry (if dunning). (ISO 8601 UTC).
offer_namestring | null
product_namestring | null
card_brandstring | null
card_last4string | null
card_exp_monthnumber | null
card_exp_yearnumber | null

Endpoints

GET/api/v1/portal/subscriptions

Auth: Customer Portal session (cookie set by the magic-link flow).

List the customer's subscriptions.

Example request

curl https://api.tokeflow.com/api/v1/portal/subscriptions \
  -H "Cookie: tf_portal_session=…"

GET/api/v1/portal/subscriptions/:id

Auth: Customer Portal session (cookie set by the magic-link flow).

Get one subscription.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d \
  -H "Cookie: tf_portal_session=…"

Example response200

{
  "id": "sub_123",
  "status": "trialing",
  "current_offer_id": "off_123",
  "billing_cycle": "daily",
  "currency": "BRL",
  "current_amount": 15000,
  "current_period_start": "2026-01-15T12:30:00.000Z",
  "current_period_end": "2026-01-15T12:30:00.000Z",
  "next_billing_at": "2026-01-15T12:30:00.000Z",
  "cancel_at_period_end": true,
  "cancelled_at": "2026-01-15T12:30:00.000Z",
  "cycles_completed": 1,
  "cycle_limit": 1,
  "trial_start": "2026-01-15T12:30:00.000Z",
  "trial_end": "2026-01-15T12:30:00.000Z",
  "preferred_installments": 1,
  "dunning_next_retry_at": "2026-01-15T12:30:00.000Z",
  "offer_name": "Premium Monthly",
  "product_name": "Streaming Plans",
  "card_brand": "visa",
  "card_last4": "4242",
  "card_exp_month": 12,
  "card_exp_year": 2027
}

POST/api/v1/portal/subscriptions/:id/add-card

Auth: Customer Portal session (cookie set by the magic-link flow).

Add a card during dunning.

Path parameters

FieldTypeRequiredDescription
idstringYes

Request fields

FieldTypeRequiredDescription
card_ciphertext_idstringYesThe single-use encrypted card reference (tok_…) for the new card, from the Bridge SDK.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/add-card \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "card_ciphertext_id": "tok_8f3c2a1b9d4e"
  }'

Example response200

{
  "id": "sub_123",
  "status": "trialing",
  "current_offer_id": "off_123",
  "billing_cycle": "daily",
  "currency": "BRL",
  "current_amount": 15000,
  "current_period_start": "2026-01-15T12:30:00.000Z",
  "current_period_end": "2026-01-15T12:30:00.000Z",
  "next_billing_at": "2026-01-15T12:30:00.000Z",
  "cancel_at_period_end": true,
  "cancelled_at": "2026-01-15T12:30:00.000Z",
  "cycles_completed": 1,
  "cycle_limit": 1,
  "trial_start": "2026-01-15T12:30:00.000Z",
  "trial_end": "2026-01-15T12:30:00.000Z",
  "preferred_installments": 1,
  "dunning_next_retry_at": "2026-01-15T12:30:00.000Z",
  "offer_name": "Premium Monthly",
  "product_name": "Streaming Plans",
  "card_brand": "visa",
  "card_last4": "4242",
  "card_exp_month": 12,
  "card_exp_year": 2027
}

GET/api/v1/portal/subscriptions/:id/available-plans

Auth: Customer Portal session (cookie set by the magic-link flow).

Plans this subscription can switch to.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/available-plans \
  -H "Cookie: tf_portal_session=…"

Example response200

{
  "current_offer_id": "off_123",
  "current_amount": 4990,
  "currency": "BRL",
  "data": [
    {
      "offer_id": "off_456",
      "offer_name": "Premium Monthly",
      "description": "Human-readable description",
      "billing_cycle": "monthly",
      "currency": "BRL",
      "amount": 4990,
      "change_kind": "upgrade",
      "change_charge_behavior": "next_renew"
    }
  ]
}

POST/api/v1/portal/subscriptions/:id/cancel

Auth: Customer Portal session (cookie set by the magic-link flow).

Cancel a subscription.

Path parameters

FieldTypeRequiredDescription
idstringYes

Request fields

FieldTypeRequiredDescription
at_period_endbooleanNoCancel at the end of the paid period (default true, most favorable). false cancels immediately.
reasonstringNoOptional cancellation reason.
survey_responsestringNoOptional cancellation survey response.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/cancel \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "at_period_end": true,
    "reason": "requested_by_customer",
    "survey_response": "string"
  }'

Example response200

{
  "id": "sub_123",
  "status": "trialing",
  "current_offer_id": "off_123",
  "billing_cycle": "daily",
  "currency": "BRL",
  "current_amount": 15000,
  "current_period_start": "2026-01-15T12:30:00.000Z",
  "current_period_end": "2026-01-15T12:30:00.000Z",
  "next_billing_at": "2026-01-15T12:30:00.000Z",
  "cancel_at_period_end": true,
  "cancelled_at": "2026-01-15T12:30:00.000Z",
  "cycles_completed": 1,
  "cycle_limit": 1,
  "trial_start": "2026-01-15T12:30:00.000Z",
  "trial_end": "2026-01-15T12:30:00.000Z",
  "preferred_installments": 1,
  "dunning_next_retry_at": "2026-01-15T12:30:00.000Z",
  "offer_name": "Premium Monthly",
  "product_name": "Streaming Plans",
  "card_brand": "visa",
  "card_last4": "4242",
  "card_exp_month": 12,
  "card_exp_year": 2027
}

POST/api/v1/portal/subscriptions/:id/change-plan

Auth: Customer Portal session (cookie set by the magic-link flow).

Change plan (upgrade/downgrade).

Path parameters

FieldTypeRequiredDescription
idstringYes

Request fields

FieldTypeRequiredDescription
to_offer_idstringYesTarget offer to switch to.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/change-plan \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "to_offer_id": "off_123"
  }'

Example response200

{
  "id": "sub_123",
  "status": "trialing",
  "current_offer_id": "off_123",
  "billing_cycle": "daily",
  "currency": "BRL",
  "current_amount": 15000,
  "current_period_start": "2026-01-15T12:30:00.000Z",
  "current_period_end": "2026-01-15T12:30:00.000Z",
  "next_billing_at": "2026-01-15T12:30:00.000Z",
  "cancel_at_period_end": true,
  "cancelled_at": "2026-01-15T12:30:00.000Z",
  "cycles_completed": 1,
  "cycle_limit": 1,
  "trial_start": "2026-01-15T12:30:00.000Z",
  "trial_end": "2026-01-15T12:30:00.000Z",
  "preferred_installments": 1,
  "dunning_next_retry_at": "2026-01-15T12:30:00.000Z",
  "offer_name": "Premium Monthly",
  "product_name": "Streaming Plans",
  "card_brand": "visa",
  "card_last4": "4242",
  "card_exp_month": 12,
  "card_exp_year": 2027
}

POST/api/v1/portal/subscriptions/:id/reactivate

Auth: Customer Portal session (cookie set by the magic-link flow).

Reactivate a pending-cancellation or paused plan.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/reactivate \
  -H "Cookie: tf_portal_session=…"

Example response200

{
  "id": "sub_123",
  "status": "trialing",
  "current_offer_id": "off_123",
  "billing_cycle": "daily",
  "currency": "BRL",
  "current_amount": 15000,
  "current_period_start": "2026-01-15T12:30:00.000Z",
  "current_period_end": "2026-01-15T12:30:00.000Z",
  "next_billing_at": "2026-01-15T12:30:00.000Z",
  "cancel_at_period_end": true,
  "cancelled_at": "2026-01-15T12:30:00.000Z",
  "cycles_completed": 1,
  "cycle_limit": 1,
  "trial_start": "2026-01-15T12:30:00.000Z",
  "trial_end": "2026-01-15T12:30:00.000Z",
  "preferred_installments": 1,
  "dunning_next_retry_at": "2026-01-15T12:30:00.000Z",
  "offer_name": "Premium Monthly",
  "product_name": "Streaming Plans",
  "card_brand": "visa",
  "card_last4": "4242",
  "card_exp_month": 12,
  "card_exp_year": 2027
}

GET/api/v1/portal/subscriptions/:id/transitions

Auth: Customer Portal session (cookie set by the magic-link flow).

A subscription's state-change history.

Path parameters

FieldTypeRequiredDescription
idstringYes

Example request

curl https://api.tokeflow.com/api/v1/portal/subscriptions/obj_1a2b3c4d/transitions \
  -H "Cookie: tf_portal_session=…"

Errors

Errors use the standard envelope. The most common cases here:

HTTPMeaning
400Invalid parameters or a state that does not allow this operation.
401Missing, expired, or invalid Dashboard session token.
403Authenticated, but the signed-in user lacks access to this entity.
404The record does not exist or is not visible to this entity.

On this page