Customer Portal sessions and config

How a customer signs in to the portal — the magic-link flow, the current session, bootstrap data, and portal configuration.

The Customer Portal lets a customer manage their own subscriptions and payment methods without contacting support. A session begins with a magic link: the customer requests a link by email, then the verify step exchanges the emailed token for a session cookie. These endpoints cover that handshake, the current session, the bootstrap payload the UI loads first, and the portal's configuration.

Everything else in the portal — subscriptions, payment methods, account — runs on the cookie established here. The portal is white-label, so its branding and allowed actions come from the merchant's portal config.

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 portal session

Returned by the list and retrieve endpoints on this page.

FieldTypeDescription
idstringPortal account id.
organization_idstring
merchant_idstringMerchant the session is scoped to.
emailstring
expires_innumberSession lifetime in seconds.

Endpoints

GET/api/v1/merchants/:merchant_id/portal-config

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

Branding and behaviour of the self-service portal your customers use to manage their subscriptions. Returns defaults when nothing has been configured yet.

Path parameters

FieldTypeRequiredDescription
merchant_idstringYes

Example request

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

Example response200

{
  "merchant_id": "mrc_123",
  "allow_cancellation": true,
  "allow_plan_change": true,
  "allow_payment_method_change": true,
  "cancellation_survey": true,
  "custom_cancellation_message": "Operation completed successfully"
}

PUT/api/v1/merchants/:merchant_id/portal-config

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

Upserts the configuration — the first call creates it, later calls replace the fields you send.

Path parameters

FieldTypeRequiredDescription
merchant_idstringYes

Request fields

FieldTypeRequiredDescription
allow_cancellationbooleanNoAllow customers to cancel via the portal.
allow_plan_changebooleanNoAllow customers to change plan via the portal.
allow_payment_method_changebooleanNoAllow customers to add a card during dunning.
cancellation_surveybooleanNoShow a cancellation survey.
custom_cancellation_messagestringNoMarkdown shown on the cancellation screen.

Example request

curl -X PUT https://api.tokeflow.com/api/v1/merchants/mrc_8a3f12d9/portal-config \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "allow_cancellation": true,
    "allow_plan_change": true,
    "allow_payment_method_change": true,
    "cancellation_survey": true,
    "custom_cancellation_message": "Operation completed successfully"
  }'

Example response200

{
  "merchant_id": "mrc_123",
  "allow_cancellation": true,
  "allow_plan_change": true,
  "allow_payment_method_change": true,
  "cancellation_survey": true,
  "custom_cancellation_message": "Operation completed successfully"
}

POST/api/v1/portal/auth/email-change/confirm

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

Confirm an email change via the emailed token.

Request fields

FieldTypeRequiredDescription
tokenstringYesToken from the confirmation email.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/auth/email-change/confirm \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "string"
  }'

POST/api/v1/portal/auth/logout

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

Clear the portal session cookie.

Example request

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

GET/api/v1/portal/auth/me

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

Get the current portal session account.

Example request

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

Example response200

{
  "id": "cpa_123",
  "organization_id": "org_123",
  "merchant_id": "mrc_123",
  "email": "customer@example.com",
  "expires_in": 1800
}

POST/api/v1/portal/auth/request-link

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

Request a portal magic-link email.

Request fields

FieldTypeRequiredDescription
organization_idstringYesOrganization the portal belongs to.
merchant_idstringYesMerchant the portal session is scoped to (from the bootstrap response). Required — the portal is single-merchant, and a session with no merchant cannot be scoped to anything.
emailstringYesCustomer email.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/auth/request-link \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "org_123",
    "merchant_id": "mrc_123",
    "email": "customer@example.com"
  }'

POST/api/v1/portal/auth/verify

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

Verify a magic-link token; sets the session cookie.

Request fields

FieldTypeRequiredDescription
tokenstringYesRaw token from the emailed magic link.

Example request

curl -X POST https://api.tokeflow.com/api/v1/portal/auth/verify \
  -H "Cookie: tf_portal_session=…" \
  -H "Content-Type: application/json" \
  -d '{
    "token": "string"
  }'

Example response200

{
  "id": "cpa_123",
  "organization_id": "org_123",
  "merchant_id": "mrc_123",
  "email": "customer@example.com",
  "expires_in": 1800
}

GET/api/v1/portal/bootstrap

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

Resolve merchant branding + flags for the portal.

Query parameters

FieldTypeRequiredDescription
merchant_idstringNo
organization_idstringNo
merchantstringNo

Example request

curl -G https://api.tokeflow.com/api/v1/portal/bootstrap \
  -H "Cookie: tf_portal_session=…" \
  --data-urlencode "merchant_id=mrc_123" \
  --data-urlencode "organization_id=org_123" \
  --data-urlencode "merchant=acme-store"

Example response200

{
  "organization_id": "org_123",
  "merchant_id": "mrc_123",
  "merchant_slug": "acme-store",
  "merchant_name": "Acme Store",
  "branding": {
    "site_title": "Acme Store",
    "favicon": "string",
    "logo_light_mode": "string",
    "logo_dark_mode": "string",
    "theme_primary_color": "#1A73E8",
    "theme_secondary_color": "#0B5394",
    "custom_url": "https://acme.example.com",
    "show_name_with_logo": false
  },
  "config": {
    "allow_cancellation": true,
    "allow_plan_change": true,
    "allow_payment_method_change": true,
    "cancellation_survey": false,
    "custom_cancellation_message": "Operation completed successfully"
  }
}

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