When to use
Use this guide to integrate raw customer cards or virtual credit cards (VCCs) through the REST API, using the public API 0.18.x contract. Start with a trip containing the selected items and travelers; see Flight booking. Checkout discovery → typed payment submission → read the outcome → follow its recovery action.Discover what the tenant may use
Call checkout with your tenant-bound booking key. The examples use placeholders only.accepted_payment_types lists only presently usable combinations. Each entry has type (spt or card), optional card_kinds (customer_card or vcc), required headers and fields, and authentication (customer_handoff or unavailable). A customer-card entry can advertise customer_handoff; a VCC has no handoff.
Do not cache this discovery. Read it on each checkout and use the returned quote ID and deadline. Never send card data speculatively: submit a card only when discovery lists card and the intended card kind. An absent combination is unavailable, even if it worked before.
Submit a card payment
Send a typed body toPOST /v1/agent_payment/submit. Authenticate with a tenant-bound booking key (jnk_…), sent as X-API-Key or as Authorization: Bearer; OAuth/JWT bearer tokens are refused for typed bodies. Idempotency-Key is required.
This curl template sends the body through standard input. Keep real card data out of shell history and command arguments; production requests belong in your secure backend.
123 with the discovered quoted_cart_id and the expiration with the credential’s expiration. Use card_kind: "customer_card" for a customer card. billing_details is optional inside payment.
For a shared payment token (SPT), the typed body is:
409 idempotency_key_reused. Card credentials are deliberately not part of that comparison, so a replay with the same key and different card details returns the first accepted attempt’s outcome rather than a new attempt; send a new key for a new credential. A request rejected before acceptance (400 credential_format_invalid) does not consume the key — correct the request and replay it with the same key, unless the Idempotency-Key itself was rejected, in which case send a valid key.
A timeout is not permission to create a new attempt. Follow recovery.action. Send a replacement credential with a new key only when the outcome permits it, cleanup is complete, and the quote is still valid. Otherwise recheckout when instructed.
Read the outcome
The typed submit response is aPaymentAttemptOutcome:
200 means a known outcome, including a decline. It does not mean the payment or booking succeeded. 202 means pending. Wait for the
Retry-After interval, then poll the attempt:
{trip_id} path parameters accept either trip_<n> or <n> (for example, trip_123 or 123). Any other format returns 400 with the fixed message invalid trip_id.
Honor the returned polling interval (Retry-After / retry_after_seconds). Keep reading the same attempt while its action is poll, including during cancellation or an unknown provider outcome. Do not submit a second payment to resolve a pending booking.
Customer authentication handoff
authentication is returned only for customer_card attempts in requires_authentication, with recovery.action: "authenticate". Send the customer to the returned authentication.url unchanged before authentication.expires_at. Never parse or reconstruct it. The link points to Jinko’s web app and has this shape:
GET /v1/trip/{trip_id}/payment_attempts/{payment_attempt_id} while the customer authenticates. VCC attempts never receive an authentication handoff.
After the customer returns, read the attempt. A browser return is not proof of authorization. Closing the browser before the deadline does not itself prove failure; poll. A verified authentication failure requires cleanup. Authentication still incomplete at the deadline becomes abandoned; poll cleanup, then recheckout when instructed.
VCC policy
VCCs have no customer authentication handoff. If a VCC needs authentication, do not open a hosted payment flow or ask a traveler to authenticate it. Obtain a replacement credential that can complete without a handoff. Wait until the attempt permits replacement and cleanup is complete; then use a new key on a valid quote, or recheckout as directed. Fulfillment never falls back to hosted payment for a VCC.Outcome codes and recovery
Always obey the returned recovery action. A code alone does not establish that cleanup has finished or the quote is still usable.
The public code meanings and caller actions are:
For
payment_credential_rejected, “same” means replacement + new key on a valid quote once quiescent. Quiescent means the earlier attempt has finished cleanup and the returned recovery action permits another attempt.
Failure table
Statuses can change during cleanup. Read the latest outcome and its recovery action before acting.Money outcomes after booking
money reports authorized, captured, released, refunded, and externally_reimbursed as Money objects with display. Use display for presentation. Read resolution_status (pending, resolved, manual_review, external_reimbursement_pending, or externally_reimbursed) and refund_reference when available; missing amounts are not evidence of zero money movement.
- Definitive booking failure before capture: the authorization is voided and released; the payment becomes
cancelledafter cleanup. - Definitive booking failure after capture: the captured amount is refunded; read
refundedandresolution_status: "resolved". - Partial delivery: exactly the booked items are captured, with the remainder released;
booking_statusispartial. - Refund to an expired or cancelled card: operations settles the refund outside the card network.
resolution_statusisexternal_reimbursement_pendinguntil settled, thenexternally_reimbursed; read theexternally_reimbursedamount andrefund_reference. Do not treat a failed refund as reimbursement completed or start another payment. - Result cannot be verified:
reconciliation_required/manual_review; contact support. Jinko does not guess whether money moved or a booking succeeded.
