Attach a token to a customer
A tokenization call returns a short-lived token. The attach call turns that token into a payment instrument on a customer record, consuming the token in the process.
This is the subscription path:
Attach exists so you have a
paymentInstrumentIdto pass toPOST /subscriptions. A one-off charge does not need it: a customer-present transaction sends the token directly toPOST /transactions. See Card on file.
To choose between FramePay and the server-side endpoint, see When to use what. For the full lifecycle of a token, including creation, expiry, and consumption details, see Token lifecycle.
Flow overview
Attach call
curl --location \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/customers/${CUSTOMER_ID}/payment-instruments" \
--header "Content-Type: application/json" \
--header "Authorization: ApiKey ${API_KEY}" \
--data '{
"token": "Token value from tokenization step"
}'
Replace staging-api.payments.ai with api.payments.ai for production environments.
The response returns a PaymentInstrument object. Its id field contains the value you pass as the paymentInstrumentId parameter on POST /subscriptions.
{
"id": "c114b68a-432e-4e94-b8ba-1658ef3258e2",
"type": "payment-card",
"creditCard": { "creditCardLastFourDigits": "1234", "brand": "Visa", "expireYear": 2034, "expireMonth": 12 },
"billingAddress": { ... }
}
Using the new payment instrument
Pass the id from the attach response as paymentInstrumentId when you create the subscription:
"paymentInstruction": { "paymentInstrumentId": "<id-from-attach-response>" }
Do not rely on it for the customer's checkout charges. The CVV the customer typed covers exactly one charge, so the instrument works once and then declines for a missing CVV. Every customer-present charge must send a fresh token on POST /transactions.
For the full customer-initiated to merchant-initiated sequence, see Card on file.
What happens on attach
- The token is consumed and cannot be reused, either for another attach call or for a transaction.
- A payment instrument is created on the customer record in an inactive state. Payments AI does not auto-charge inactive instruments; the instrument transitions to
activeonce a payment succeeds on it. In the subscription flow that payment is the one the customer completes on the hosted payment form. See Payment instrument lifecycle. - If the attach call fails due to token expiration, network drops, or validation errors, the token cannot be reused. You must re-tokenize the card to obtain a new one.
Common mistakes
| Mistake | Result |
|---|---|
| Reusing a token across two attach calls | The second call returns 422 (UnprocessableContent) because the token was consumed by the first call. |
Sending the token after its expiratedAt has passed | The attach call fails. You must re-tokenize the card. |
Treating the new paymentInstrumentId as auto-chargeable | Subscriptions created against an inactive instrument return a status: "pending" response and require an initial hosted-form payment. See Subscription troubleshooting. |
Attaching a token that was already spent on POST /transactions | 422. The transaction consumed the token and already returned a payment instrument, so there is nothing left to attach. |
Relying on the new paymentInstrumentId for repeat customer-present charges | The CVV from the token covers exactly one charge. The first payment on the instrument succeeds; the next declines with cvvResponse.originalMessage: "No CVC/CVV provided, but was required". Send a fresh token for every customer-present charge. See Card on file. |