POST the moment a booking is confirmed or fails.
The one-line version:
Prerequisites
- A Jinko account and a user-bound API key (
jnk_...). Get one. - An HTTPS endpoint that can receive a
POST(must behttps://and publicly reachable).
Tenant-key bookings deliver to the tenant’s own subscription
A booking made with a tenant key is owned by the tenant, not by a person, and its events go to the subscriptions registered against that tenant in the dashboard. Nothing about the payload, the headers, or the signature differs from a user-key delivery: the only difference is which subscription list the platform resolves. Register the endpoint once, in the dashboard, with your tenant picked in the selector. Then book with the tenant key. Every subscription that tenant owns and that names the event receives the same signedPOST a user-key booking would produce.
Availability, as of 7 September 2026. Tenant-key delivery arrives with published contract
0.5.0. On sandbox it works once that release is deployed there; check info.version on the OpenAPI document for the environment you are calling. On production it additionally waits on a separate platform release, so a production booking made with a tenant key does not reach a tenant subscription yet.Bookings made with a user-bound key are unaffected in both environments and deliver normally.Nothing on your side needs to change when it lands: register the subscription in the dashboard now and it starts receiving. This note is removed once both releases have shipped.1) Register an endpoint
- Dashboard
- API
Go to Dashboard → Webhooks, click Add webhook, paste your URL, pick the events, and Create. Copy the signing secret shown once. You’ll need it to verify deliveries.
2) Events
Exactly one of the three fires per trip. They are mutually exclusive.
More event types will be added over time. Treat the
event field as an open enum and ignore events you don’t handle.
booking.partial arrived in published contract 0.2.0. Check info.version in the OpenAPI document to confirm which contract an environment is serving.
3) Payload
Deliveries are intentionally thin: identifiers only, no traveler PII. Fetch full detail withget_booking using the booking_ref.
booking.partial adds a data object
booking.partial carries one extra top-level field, data, describing what actually happened per item and how much was captured. booking.completed and booking.failed do not carry data, so nothing changes for consumers you already have in production.
Amounts here are in major units (
188.65), matching the Money shape used across the trip and checkout responses. This differs from the minor-unit form used elsewhere in the platform, so don’t divide by 100.
The
event_id for a partial is evt_<fulfillment_cart_id>_booking.partial, one per trip. Retries reuse it, so your existing dedupe on X-Jinko-Event-Id covers it with no change.4) Verify the signature
ComputeHMAC-SHA256(secret, "<X-Jinko-Timestamp>.<raw request body>") and compare it, in constant time, to the hex in X-Jinko-Signature (after the sha256= prefix). Use the raw request body: parsing and re-serializing the JSON will change the bytes and break the check.
- Node.js
- Python
X-Jinko-Timestamp is older than your tolerance (e.g. 5 minutes) to guard against replays. Respond 2xx once you’ve accepted the event.
5) Retries & idempotency
- A non-
2xxresponse (or a timeout) is retried with exponential backoff, up to 8 attempts over several hours. - Retries mean you may receive the same event more than once. Deduplicate on
X-Jinko-Event-Id(a given business event always carries the same id). - Return
2xxas soon as you’ve durably recorded the event; do slow work asynchronously so you don’t trip the delivery timeout.
6) Test it
Use Send test in the dashboard, or:"livemode": false and booking_ref: "JNK-TEST00", so you can confirm your signature handling end-to-end without a real booking.