Skip to main content
POST
Submit a typed SPT payment with Idempotency-Key, or a legacy flat Shared Payment Token
Typed submissions require a jnk_ API key via X-API-Key (ApiKeyAuth) or Authorization: Bearer (BearerAuth), a tenant-bound booking scope, quote_id and Idempotency-Key, and return a PaymentAttemptOutcome (200 known outcome / 202 pending). OAuth/JWT bearer tokens are supported only for the legacy flat token body, which keeps its existing authorization response. Request bodies are limited to 16 KiB.

Authorizations

X-API-Key
string
header
required

Headers

Idempotency-Key
string

Required on a typed submission (a body with payment); without it the request is refused with 400 CREDENTIAL_FORMAT_INVALID. Ignored on the legacy body. 1–255 printable ASCII characters. Reuse only for the same payment submission: the same key with the same body replays the first outcome, with a different body it is refused.

Required string length: 1 - 255
Pattern: ^[ -~]+$(?![\s\S])

Body

application/json
trip_id
string
required
quote_id
string
required

The quote the traveler approved: the quote_id checkout returned. The payment is taken against this quote only; a quote that is no longer payable is refused with 410 QUOTE_EXPIRED and nothing is charged.

Pattern: ^[1-9][0-9]{0,17}$(?![\s\S])
Example:

"2097152"

payment
object
required

Response

Legacy authorization result or typed payment outcome

payment_attempt_id
string
required
trip_id
string
required

The trip this attempt pays, written with a trip_ prefix (trip_1048576); the trip answers carry the same id without it (1048576). Strip the prefix to compare the two.

Example:

"trip_1048576"

quote_id
string
required

The quote this payment is taken against.

Example:

"2097152"

quoted_cart_id
integer
required
deprecated

Deprecated: use quote_id instead. The same quote as an integer.

payment_status
enum<string>
required
Available options:
not_started,
pending,
requires_authentication,
authorized,
captured,
declined,
cancelling,
cancelled,
expired,
failed
booking_status
string
required

The detailed status of the booking this payment started, not_scheduled until booking begins. booking_state on GET /v1/trip/{trip_id} is its summary.

payment_error
object | null
required

Why the payment has not gone through, or null. On the checkout_url payment page, a card the issuer declines (card_declined) or whose authentication fails (authentication_failed) is reported here while payment_status stays pending and recovery.action is poll: the payer can use another card on the same page until the quote expires. It returns to null when a card is authorized. CARD_ALIAS_EXPIRED: The card alias expired before the booking was dispatched. Follow recovery.action; when it is retry_new_key: Submit the card again on the pay hostname with a new Idempotency-Key.

recovery
object
required
recovery_status
enum<string>
required
Available options:
automatic,
manual_review
fulfillment_cart_id
integer
deprecated

Deprecated: use booking_ref instead. An internal number for the booking this payment funds.

failure_reason
string | null

Why the booking failed, when it failed after payment and the cause is known: offer_unavailable, price_changed, booking_not_created (the supplier holds no booking; nothing was booked and no money was taken), booking_cancelled_at_provider, ticketing_refused. Null otherwise. For offer_unavailable, the supplier no longer sells the priced offer. Nothing was booked and the card authorisation was released. Search again and book a new offer. The booking.failed webhook carries the same reason with a sentence to show the traveller (failure_message).

Example:

"booking_not_created"

items
object[]
booking_ref
string

The booking reference. Absent until the booking has one; never null.

quote_expires_at
string<date-time>
retry_after_seconds
integer

Seconds to wait before reading the payment attempt again. Present only while recovery.action is poll; absent otherwise, never null.

authentication
object

Where the customer authenticates when recovery.action is authenticate: open url before expires_at. For a Shared Payment Token (spt), url is a Jinko-hosted page that needs the token's hashed value: read the issued token's next_action.use_stripe_sdk.value with your own Stripe secret key and open url + "#hv=" + <value>, passing the value unchanged. The value travels in the URL fragment, which keeps it out of server logs.

money
object