Payment Instruments

Save cards on file as payment instruments and reuse them for repeat charges, subscriptions, and other merchant-initiated transactions.

A payment instrument is a saved payment method — typically a card — kept on file for a customer so you can charge it again without re-collecting card data. Instruments are the backbone of repeat purchases, one-click checkout, and merchant-initiated charges such as subscription renewals.

Tokeflow stores only a non-sensitive reference and metadata for each instrument (pi_…, brand, last 4, expiry). The card itself is encrypted at collection time and is never handled by your servers.

Tokeflow is a payment orchestration platform. It does not process or settle funds — your connected payment providers do. A payment instrument is an orchestration-level reference that lets Tokeflow route a saved-card charge to the right provider on your behalf.

How instruments come to exist

You never create a payment instrument by sending raw card numbers to the API. Instead, a card is enrolled client-side through the Bridge SDK using a zero-dollar setup verification — a transaction with charge_type: "setup_verification". The provider verifies the card is valid (and, where applicable, runs 3DS) without capturing money. On success, Tokeflow persists a reusable payment instrument and returns its pi_… id.

The card-collection and enrollment flow is a client-side concern handled entirely by the Bridge SDK. See the SDK overview and card enrollment guides for the browser implementation. This page covers the server-side REST API for managing and using instruments after they exist.

:::tip Secure card collection Tokeflow's secure fields run inside isolated, cross-origin iframes. Card data is encrypted in the browser and never touches your servers, so a payment instrument is the only card reference your backend ever sees. :::

How instruments are used

Once an instrument exists, reference it by id wherever a saved card can be charged:

  • Saved-card charges — pass payment_instrument_id to POST /api/v1/transactions to charge the stored card. No card data is re-collected.
  • Subscriptions — set or change the card a subscription bills against via change-payment-instrument. Future renewals run as merchant-initiated charges against the new instrument.
{
  "payment_method": "credit_card",
  "charge_type": "payment",
  "country": "BR",
  "customer_id": "cust_john_01",
  "payment_instrument_id": "pi_a1b2c3",
  "amount": 15000,
  "currency": "BRL"
}

The payment instrument object

FieldTypeDescription
idstringUnique identifier, prefixed pi_.
merchant_idstringMerchant that owns the instrument (mrc_…).
customer_idstringCustomer the instrument belongs to (cust_…).
instrument_typestringInstrument family. Currently card.
card_brandstring | nullCard brand, e.g. visa, mastercard, amex.
card_typestring | nullcredit or debit.
last4string | nullLast 4 digits of the card.
binstring | nullIssuer identification number (6- or 8-digit).
issuer_countrystring | nullISO 3166-1 alpha-2 country of the issuer.
exp_monthinteger | nullCard expiration month (1–12).
exp_yearinteger | nullCard expiration year (4-digit).
statusstringactive, expired, or revoked.
created_atstringCreation timestamp (ISO 8601 UTC).

Full card data is never stored by you. A payment instrument is only a stable reference (pi_…) plus non-sensitive metadata — brand, last 4, expiry, and issuer details. The primary account number cannot be read back through the API.

Status values

StatusMeaning
activeUsable for charges.
expiredPast the card's expiration date; cannot be charged.
revokedDisabled for security or compliance reasons; cannot be charged.

Example object

{
  "id": "pi_a1b2c3",
  "merchant_id": "mrc_123",
  "customer_id": "cust_john_01",
  "instrument_type": "card",
  "card_brand": "visa",
  "card_type": "credit",
  "last4": "4242",
  "bin": "424242",
  "issuer_country": "BR",
  "exp_month": 12,
  "exp_year": 2028,
  "status": "active",
  "created_at": "2026-01-15T12:30:00.000Z"
}

Endpoints

All instrument endpoints are merchant-scoped and live under a merchant path.

  • Merchant key — the merchant is inferred from the key; supply your merchant id in the path.
  • Organization key — pass the target merchant id in the path; the org key must have access to that merchant.

Required scopes: instruments:read for reads, instruments:write for mutations.

GET/api/v1/merchants/{merchant_id}/payment-instruments

List a merchant's payment instruments. Supports pagination and filtering.

Auth: Organization key (scoped to the merchant) or Merchant key.

Query parameters

FieldTypeRequiredDescription
customer_idstringNoFilter to one customer's instruments.
statusstringNoFilter by active, expired, or revoked.
card_brandstringNoFilter by brand, e.g. visa.
card_typestringNoFilter by credit or debit.
last4stringNoFilter by last 4 digits.
binstringNoFilter by issuer identification number.
issuer_countrystringNoFilter by ISO 3166-1 alpha-2 issuer country.
pageintegerNoPage number (default 1, min 1).
limitintegerNoItems per page (default 20, max 100).
curl "https://api.tokeflow.com/api/v1/merchants/mrc_123/payment-instruments?customer_id=cust_john_01&status=active&limit=20" \
  -H "Authorization: Bearer sk_live_mer_xxx"

Response 200 OK

{
  "success": true,
  "data": [
    {
      "id": "pi_a1b2c3",
      "merchant_id": "mrc_123",
      "customer_id": "cust_john_01",
      "instrument_type": "card",
      "card_brand": "visa",
      "card_type": "credit",
      "last4": "4242",
      "bin": "424242",
      "issuer_country": "BR",
      "exp_month": 12,
      "exp_year": 2028,
      "status": "active",
      "created_at": "2026-01-15T12:30:00.000Z"
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 1,
      "total_pages": 1,
      "has_next": false,
      "has_prev": false
    }
  },
  "request_id": "req_8f3c2a",
  "timestamp": "2026-01-15T12:30:00.000Z"
}

Use customer_id plus status=active to render a customer's wallet — for example, the saved cards shown at checkout or in a billing portal.

PATCH/api/v1/merchants/{merchant_id}/payment-instruments/{payment_instrument_id}

Update an instrument's status. The status is the only mutable field.

Auth: Organization key (scoped to the merchant) or Merchant key.

Body

FieldTypeRequiredDescription
statusstringYesNew status: active, expired, or revoked.
curl -X PATCH \
  "https://api.tokeflow.com/api/v1/merchants/mrc_123/payment-instruments/pi_a1b2c3" \
  -H "Authorization: Bearer sk_live_mer_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "status": "revoked" }'

Response 200 OK

{
  "success": true,
  "data": {
    "id": "pi_a1b2c3",
    "merchant_id": "mrc_123",
    "customer_id": "cust_john_01",
    "instrument_type": "card",
    "card_brand": "visa",
    "card_type": "credit",
    "last4": "4242",
    "bin": "424242",
    "issuer_country": "BR",
    "exp_month": 12,
    "exp_year": 2028,
    "status": "revoked",
    "created_at": "2026-01-15T12:30:00.000Z"
  },
  "request_id": "req_91ad04",
  "timestamp": "2026-01-15T12:31:00.000Z"
}

DELETE/api/v1/merchants/{merchant_id}/payment-instruments/{payment_instrument_id}

Revoke an instrument. After revocation it can no longer be charged. Active subscriptions billing against it must be moved to another instrument first.

Auth: Organization key (scoped to the merchant) or Merchant key.

curl -X DELETE \
  "https://api.tokeflow.com/api/v1/merchants/mrc_123/payment-instruments/pi_a1b2c3" \
  -H "Authorization: Bearer sk_live_mer_xxx"

Response 204 No Content

HTTP/1.1 204 No Content

Revoking an instrument is permanent. If a subscription still bills against it, move the subscription to another instrument with change-payment-instrument before revoking, or its next renewal will fail.

Errors

Failures use the standard error envelope.

HTTPTypeWhen
401authentication_errorMissing or invalid API key.
403authorization_errorKey lacks the required scope, or the org key cannot access this merchant.
404not_found_errorInstrument or merchant not found.
422business_rule_errorStatus transition not allowed (e.g. reactivating a revoked instrument).
{
  "error": {
    "type": "not_found_error",
    "code": "PAYMENT_INSTRUMENT_NOT_FOUND",
    "message": "Payment instrument pi_a1b2c3 was not found for this merchant.",
    "details": {},
    "request_id": "req_8f3c2a",
    "timestamp": "2026-01-15T12:30:00.000Z"
  }
}

On this page