Skip to main content

Authorize and capture

A two-step payment: first authorize the card to reserve funds, then capture to settle them. Use this when you need to confirm funds are available before you commit the charge, such as verifying an order before shipping.

The key difference from a standard sale: set type: "authorize" instead of "sale". The authorization reserves funds without taking them. You capture later by creating a second transaction with type: "sale".

Flow overview

Authorize and capture builds on top of a paymentInstrumentId already attached to a customer. Tokenization is a prerequisite step that differs between environments and integration paths. The authorize and capture calls themselves are identical across paths once you have the paymentInstrumentId.

Stage flow

On stage there is no production tokenization host. Tokenize the card through the staging tokenization endpoint, attach the token to the customer, then run authorize and capture.

See Tokenization endpoint for the stage body shape.

Production flow — FramePay

For web integrations on production, the recommended path is FramePay. Card data is collected by hosted iframe fields, never touches your server, and your PCI scope stays at SAQ A.

See FramePay for the SDK integration.

Production flow — server-side tokenization endpoint

For native mobile apps or backend-only integrations on production, the card data is tokenized through the dedicated production tokenization host (tokenization.payments.ai). Raw card data flows through your server, placing your PCI scope at SAQ D.

See When to use FramePay vs server-side for the choice between paths and Tokenization endpoint for the production body shape.

Prerequisites

Set your environment variables first. The POST /transactions endpoint sits under the Public API, so the host is staging-api.payments.ai on stage and api.payments.ai on production. Tokenization (the step that produces the paymentInstrumentId) does not share this host pattern — stage and production tokenization use different hosts, paths, and request body shapes. See the Flow overview above for the three integration paths and Tokenization endpoint for the body differences between environments.

Stage:

export API_HOST="staging-api.payments.ai"
export API_KEY="Your API Key Here"
export ORGANIZATION_ID="Your Organization ID Here"
export CUSTOMER_ID="Customer ID Here"

Production:

export API_HOST="api.payments.ai"
export API_KEY="Your API Key Here"
export ORGANIZATION_ID="Your Organization ID Here"
export CUSTOMER_ID="Customer ID Here"

The curl examples below use ${API_HOST} because POST /transactions shares one structure across environments — only the host changes. This is not the case for the tokenization step.

1. Get the payment instrument id

curl -X GET \
"https://${API_HOST}/v1/public-api/organizations/${ORGANIZATION_ID}/customers/${CUSTOMER_ID}/payment-instruments" \
--header "Content-Type: application/json" \
--header "Authorization: ApiKey ${API_KEY}"

2. Authorize the transaction

Setting type: "authorize" reserves funds without capturing them. Note the transaction id from the response because you need it to track the authorization.

curl -X POST \
"https://${API_HOST}/v1/public-api/organizations/${ORGANIZATION_ID}/transactions" \
--header "Content-Type: application/json" \
--header "Authorization: ApiKey ${API_KEY}" \
--data-raw '{
"type": "authorize",
"customerId": "Customer ID Here",
"currency": "USD",
"amount": 1,
"paymentInstruction": {
"paymentInstrumentId": "PaymentInstrumentID Here"
}
}'

3. Capture the transaction

To settle the reserved funds, create a new transaction with type: "sale" using the same customerId and paymentInstrumentId.

curl -X POST \
"https://${API_HOST}/v1/public-api/organizations/${ORGANIZATION_ID}/transactions" \
--header "Content-Type: application/json" \
--header "Authorization: ApiKey ${API_KEY}" \
--data-raw '{
"type": "sale",
"customerId": "Customer ID Here",
"currency": "USD",
"amount": 1,
"paymentInstruction": {
"paymentInstrumentId": "PaymentInstrumentID Here"
}
}'

Authorization expiry

The issuing bank holds reserved funds for a limited window set by the card scheme. If you do not capture within the window, the hold expires automatically and the funds are released back to the customer. Typical card-scheme defaults:

SchemeTypical hold window
Visa~7 days
Mastercard~30 days
American Express~7 days
Discover~10 days

These are card-scheme defaults rather than PaymentsAI rules. The actual window depends on the issuing bank and merchant category. Treat them as planning guidance, not contractual guarantees. If you need to release an authorization before its window expires, contact your Integration Consultant, as the public API does not currently expose a void endpoint.

Capture amount

The merchant guide and PaymentsAI's documented flow show the capture (sale) amount matching the original authorization. Partial capture (capturing less than the authorized amount and releasing the difference) is not currently documented for the public API. If you need it, confirm the behavior with your Integration Consultant before relying on it.

Notes

  • The customerId and paymentInstrumentId on the capture call must match the original authorization. PaymentsAI does not let you capture an authorization against a different payment instrument.
  • A successful authorize returns status: "waiting". A successful capture returns status: "completed". The original authorize transaction stays on record alongside the capture.