Submit Charge with Tokenized Payment Method
Charge a saved payment method with the customer absent. Call this endpoint only from your backend, from an allowlisted IP.
Pre-requisite
When integrating with Codapay APIs, ensure you adhere to the following standards:
Use HTTPS protocol.
TLS 1.2 or higher
Sandbox
https://sandbox.codapayments.com/airtime
Production
https://airtime.codapayments.com/airtime
Endpoint
POST {Base URL}/v1/payment/token/charge
Headers
Content-Type
yes
application/json; charset=UTF-8
X-API-Key
yes
Same value as Init v2 apiKey. Identifier only — not the JWT HMAC secret.
Authorization
yes
Bearer <JWT> (HS256). See Authentication.
Idempotency-Key
optional
Unique identifier of the request to avoid duplicate charges.
Idempotency-Key implementation is strongly recommended to ensure your order doesn't get charged twice unintentionally.
Send a unique
Idempotency-Keyper logical charge attempt (UUID recommended).Retry only the same request body (amount,
payment_method_id, order identifiers, etc.) with the same key after timeouts.Stop retrying the same key before the 24-hour boundary. After TTL expiry, the platform may treat the request as a new charge.
Request parameters
country
number
yes
Numeric country code. Must match JWT country.
currency
number
yes
Numeric currency code. Must match JWT currency.
payType
number
yes
Payment Channel Id. Must match JWT payType.
projectId
number
yes
Same project as Init. Must match JWT projectId.
orderId
string
yes
Your unique order id for this charge. Must match JWT orderId.
offSessionType
string
yes
Same agreement type as the CIT that saved the card. One of Unscheduled, Subscriptions, Installments. Must match JWT offSessionType.
items
array
yes
Non-empty. Each item: code, price, name. Must match JWT items exactly.
paymentMethodId
string
yes
Saved payment method id from PAYMENT_METHOD_ADDED Event (paymentMethod.id) or from the query parameter PaymentMethodId of Successful Payment notification
Sample Token Charge body
Immediate response
txnId
number
Coda transaction id. 0 if the request was rejected before a charge was created.
resultCode
integer
431 = accepted, processing. 0 = success (rare on this path). Other values = error.
resultDesc
string
English message on error. null when the charge is accepted for processing (431).
Accepted (processing):
Do not treat 431 as paid. Wait for the complete notification or Inquiry.
Rejected example:
Authentication (Token Charge)
Token Charge endpoint uses two credentials:
X-API-Key
Same string / key as Init Payment API apiKey.
HMAC signing secret
Separate secret Coda gives you out of band. Used only to sign the JWT. Never put it in X-API-Key, the JSON body, logs, or git.
There is no Coda endpoint that issues the JWT. Your server builds and signs it per request.
JWT header
Algorithm is HS256 only. Other algorithms are rejected.
JWT claims
exp - iat must be ≤ 300 seconds. Coda allows about 30 seconds of clock skew. Every listed claim is required. After signature verify, each claim must exactly match the JSON body (same types). Mismatch → resultCode 103.
iat
number
Unix seconds UTC. Must be ≤ now (with skew).
exp
number
Unix seconds UTC. Must be > now. exp - iat ≤ 300.
orderId
string
Match body orderId.
projectId
number
Match body projectId. Used with country to resolve the merchant.
country
number
Match body country.
currency
number
Match body currency.
payType
number
Match body payType.
offSessionType
string
Match body offSessionType.
items
array of {code, price, name}
Same length and fields as body items. This binds the amount.
paymentMethodId
string
Match body paymentMethodId.
Do not include iss, jti, kid, apiKey, userInitiated, shopper, profile, or paymentMethods in the JWT. This endpoint is MIT-only; Coda sets customer-absent internally.
Sign (Node-style sketch)
IP allowlist (Token Charge)
Coda only accepts Token Charge from IPv4 addresses or CIDR ranges you give your account manager (NAT / load-balancer egress of the servers that call the API — not developer laptops unless that is intentional for sandbox).
Who sends IPs
You, before go-live
Format
Exact IPv4 and/or CIDR (e.g. 203.0.113.10, 198.51.100.0/24)
If missing or IP not listed
Token Charge is rejected
When your egress IPs change, notify Coda before cutover.
Last updated
Was this helpful?