API reference overview
Conventions for the Tokeflow REST API — base URL and versioning, authentication, request and response envelopes, resource IDs, money, pagination, idempotency, and rate limits.
The Tokeflow API is a JSON-over-HTTPS interface for payment orchestration. Use it to manage customers, run checkout sessions, create and capture transactions, issue refunds, model your catalog, and drive subscriptions — all standardized under your own brand, across every payment provider you connect.
Tokeflow orchestrates payments; it does not process or settle funds. Authorization, capture, and settlement are performed by the connected payment providers. Tokeflow normalizes their behavior behind one consistent API so your integration stays the same no matter who is behind it.
This page is the conventions hub. Read it once, and every endpoint page in this reference will behave the way you expect.
New to Tokeflow? Start with the Authentication guide to provision keys, then come back here for the wire format.
Base URL and versioning
All requests go to a single base URL:
https://api.tokeflow.comThe API uses URI versioning. Every endpoint lives under a version prefix, and the current version is v1:
https://api.tokeflow.com/api/v1/{resource}Breaking changes ship under a new version prefix (for example /api/v2). Additive, backward-compatible changes — new fields, new enum values, new endpoints — may appear within v1, so build clients that ignore unknown fields.
Tokeflow is white-label by design. Whether a request fans out to one provider or cascades across several is governed by your routing configuration, not by the API surface. The request and response shapes documented here are stable regardless of which provider ultimately handles the payment.
Authentication
Authenticate server-to-server requests with a secret API key in the Authorization header using the Bearer scheme:
Authorization: Bearer sk_live_mer_…Keys are scoped to exactly one entity:
| Key type | Prefix | Scope | Merchant targeting |
|---|---|---|---|
| Merchant secret | sk_live_mer_… | One merchant | Merchant is inferred — no merchant_id needed |
| Organization secret | sk_live_org_… | Every merchant in the org | Identify the target merchant with merchant_id |
Public keys (pk_live_org_… / pk_live_mer_…) are restricted to client-safe scopes and are safe to embed in browser code. Secret keys (sk_*) must never be exposed client-side.
Permissions follow a resource:action model (for example transactions:read, products:write). A request that authenticates but lacks the required scope returns 403 (authorization_error).
Treat secret keys like passwords. Never ship an sk_* key to a browser, mobile app, or any client you do not control. For client-side card collection, use a public key with the Bridge SDK instead.
See Authentication for key anatomy, rotation, and scope details.
Organization keys and merchant_id
When you use an Organization key against a merchant-scoped resource, you must tell Tokeflow which merchant you mean:
- On list and get requests, pass
merchant_idas a query parameter. - On create requests, pass
merchant_idin the request body.
Merchant keys never need this — the merchant is derived from the key.
# Organization key: merchant_id is required
curl https://api.tokeflow.com/api/v1/customers?merchant_id=mrc_a1b2c3 \
-H "Authorization: Bearer sk_live_org_…"
# Merchant key: merchant is inferred
curl https://api.tokeflow.com/api/v1/customers \
-H "Authorization: Bearer sk_live_mer_…"Request format
Send and accept JSON.
| Header | Value |
|---|---|
Authorization | Bearer <secret_key> |
Content-Type | application/json (on requests with a body) |
Accept | application/json |
A typical request:
curl -X POST https://api.tokeflow.com/api/v1/customers \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Joao da Silva",
"email": "joao@example.com"
}'Response envelope
Every response is wrapped in a consistent envelope. Your code reads success to branch, then data for the payload — never the top-level object directly.
Success envelope
A successful response sets success: true and carries the resource (or array of resources) in data:
{
"success": true,
"data": {
"id": "cust_9a8b7c",
"name": "Joao da Silva",
"email": "joao@example.com",
"created_at": "2026-01-15T12:30:00.000Z"
},
"request_id": "req_8f3c…",
"timestamp": "2026-01-15T12:30:00.000Z"
}Where things live:
| Field | Description |
|---|---|
success | Always true on a 2xx response. |
data | The resource (single object) or the collection (array, on list endpoints). |
meta | Present on list responses. Holds pagination. Omitted for single-resource responses. |
request_id | Unique ID for the request. Quote it in support tickets and log it on your side. |
timestamp | ISO 8601 UTC time the response was generated. |
For a list endpoint, data is the array and meta.pagination describes the page:
{
"success": true,
"data": [
{ "id": "cust_9a8b7c", "name": "Joao da Silva" },
{ "id": "cust_4d5e6f", "name": "Maria Souza" }
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 42,
"total_pages": 3,
"has_next": true,
"has_prev": false
}
},
"request_id": "req_8f3c…",
"timestamp": "2026-01-15T12:30:00.000Z"
}Error envelope
Errors are never wrapped in data. They use a dedicated shape with a stable, machine-readable code:
{
"error": {
"type": "validation_error",
"code": "INVALID_FIELD",
"message": "The 'currency' field must be a valid ISO 4217 code.",
"details": {
"field": "currency"
},
"request_id": "req_8f3c…",
"timestamp": "2026-01-15T12:30:00.000Z"
}
}The HTTP status maps directly to the error type:
| Status | type |
|---|---|
| 400 | validation_error |
| 401 | authentication_error |
| 403 | authorization_error |
| 404 | not_found_error |
| 409 | conflict_error |
| 422 | business_rule_error |
| 429 | rate_limit_error |
| 500 | internal_server_error |
Branch on error.code (a stable string), not on error.message (human-readable and subject to change). See Errors for the full catalog.
const body = await res.json();
if (!res.ok) {
// body.error.type, body.error.code, body.error.message
throw new Error(`[${body.error.code}] ${body.error.message}`);
}
return body.data;Resource IDs
Every Tokeflow resource has a stable, opaque ID with a type prefix. The prefix tells you the resource type at a glance — treat the rest as an opaque string and never parse it.
| Prefix | Resource |
|---|---|
org_ | Organization |
mrc_ | Merchant |
cust_ | Customer |
pfa_ | Product family |
prd_ | Product |
ofr_ | Offer |
opr_ | Offer price |
oft_ | Offer transition |
cks_ | Checkout session |
cki_ | Checkout item |
cke_ | Checkout event |
tx_ | Transaction |
ref_ | Refund |
ord_ | Order |
sub_ | Subscription |
pi_ | Payment instrument |
tok_ | Card token (SDK) |
IDs are opaque. Do not infer meaning from their contents, assume a fixed length, or generate them yourself — always use the value Tokeflow returns.
Data formats
Tokeflow standardizes formats so your data is unambiguous across providers and regions.
Money
Amounts are integers in the currency's minor units (for example, cents). Never send a decimal.
| Amount | Currency | amount |
|---|---|---|
| R$150.00 | BRL | 15000 |
| US$99.00 | USD | 9900 |
Always pair an amount with its ISO 4217 currency code (for example "BRL", "USD"). An amount without a currency is ambiguous and is rejected.
Country, currency, and dates
| Field | Format | Example |
|---|---|---|
country | ISO 3166-1 alpha-2 | "BR" |
currency | ISO 4217 | "BRL" |
| Timestamps | ISO 8601, UTC | "2026-01-15T12:30:00.000Z" |
Idempotency
Create and charge mutations are idempotent. Send a unique Idempotency-Key header (or an idempotency_key body field) and Tokeflow guarantees the operation runs at most once.
curl -X POST https://api.tokeflow.com/api/v1/transactions \
-H "Authorization: Bearer sk_live_mer_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 4f1c2a9e-7b3d-4d2a-9f10-2e5a8c1b6d44" \
-d '{ "amount": 15000, "currency": "BRL", "payment_method": "pix" }'Replaying the same key returns the original result — HTTP 200 on a replay versus HTTP 201 on the first create — instead of creating a duplicate. Generate a fresh key (such as a UUID) per logical operation, and reuse it when retrying after a network failure.
Always set an idempotency key on POST /transactions. It is your safety net against double charges when a request times out and you retry.
See Idempotency for the full semantics.
Rate limits
Requests are rate limited per API key. The default is 100 requests per 60-second window. Exceeding the limit returns HTTP 429 with a rate_limit_error.
Handle 429 with exponential backoff and jitter, and spread bulk operations over time rather than bursting. See Rate limits for details.
Pagination and filtering
List endpoints are paginated with two query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 (min 1) | 1-indexed page number. |
limit | integer | 20 (max 100) | Items per page. |
The response carries the page state in meta.pagination:
curl "https://api.tokeflow.com/api/v1/customers?page=2&limit=50" \
-H "Authorization: Bearer sk_live_mer_…"Most list endpoints also accept resource-specific filters (for example status, date range, currency). Each endpoint page documents its own filters. See Pagination and filtering for the shared conventions.
How a request flows
Tokeflow authenticates the key, applies your routing rules (including resilience and fallback), forwards to the selected provider, and normalizes the provider's response into the standard envelope. Your client always sees the same shape.
Resource groups
Every endpoint below accepts an Organization or a Merchant key. With an Organization key, add merchant_id where the endpoint is merchant-scoped (as noted on each page).
| Group | Prefix | Description |
|---|---|---|
| Customers | cust_ | Create and manage payers, including documents and contact details. |
| Checkout Sessions | cks_ | Hosted/embedded checkout flows: line items, customer identification, and events. |
| Transactions | tx_ | Create, retrieve, capture, and void payments; inspect attempts and routing timeline. |
| Refunds | ref_ | Full or partial refunds against captured transactions. |
| Orders | ord_ | Order records that group transactions across API, checkout, and renewal flows. |
| Subscriptions | sub_ | Recurring billing: offers, lifecycle, dunning, pause/resume, and offer changes. |
| Payment Instruments | pi_ | Saved payment methods on file for merchant-initiated and repeat charges. |
| Catalog | — | Product families, products, offers, offer prices, and offer transitions. |
| Webhooks | — | Normalized, signed event notifications for payment and lifecycle changes. |
Catalog at a glance
The catalog models what you sell and how it is priced.
| Catalog resource | Prefix | Description |
|---|---|---|
| Product Families | pfa_ | Top-level grouping for related products. |
| Products | prd_ | A sellable item — one_time or recurring. |
| Offers | ofr_ | A purchasable configuration of a product, including its billing cycle. |
| Offer Prices | opr_ | Priced variants of an offer (amount + currency). |
| Offer Transitions | oft_ | Rules for moving a subscription from one offer to another. |
Next steps
- Authentication — provision keys and understand scopes.
- Errors — the full error catalog and codes.
- Idempotency and Rate limits — safe retries at scale.
- Webhooks — receive and verify signed events.