Sessions are how the kurnl Marketplace hands a subscriber over to your hosted checkout page. The Marketplace creates a session, redirects the subscriber to your external_checkout_url with ?session_id=<id> appended, and your page reads the session to get the plan, location, and delivery mode. See the flow guides: CKO-03 Direct, CKO-03 Home-Drop, CKO-03 Anonymous.

Endpoints

A session you have read does not expire. The first time your checkout page reads a session (GET .../sessions/{session_id}), kurnl marks it redirected — the shopper has arrived on your page — and from then on it is never reaped. It ends as completed or cancelled. So a slow payment, a bank transfer, or a customer who finishes the next morning can still be provisioned. A session that is never read expires 2 hours after it is created. That window only has to cover the hop from the kurnl Marketplace to your checkout page. Any endpoint that touches such a session returns 410 Gone and marks it expired on the same call; that is final, there is no way to revive it. Session lifecycle: pendingredirectedcompleted | cancelled, or pendingexpired if your page never read it. expired and cancelled surface as 410.
Read the session once, early, when your checkout page renders — that read is what protects the order. If your integration caches the session body and never calls kurnl again before payment, the session stays pending and can still expire under you.

POST /partner/external-checkout/sessions

Creates a pending session and returns your hosted checkout URL with session_id appended.
This is the kurnl Marketplace’s endpoint, not part of the partner contract. It is documented so you can read what arrives in the session your page receives — do not call it. If you originate checkouts yourself, because customers buy on your own site, that is CKO-04 provider-initiated: resolve the address with the serviceability endpoints and provision with POST /provisioning/provider-initiated. No session is involved.
Auth: none required. If a signed-in kurnl user’s Bearer token is supplied, the session is linked to that account (so it appears in their hub).

Request body

Response — 201 Created

In sandbox, external_checkout_url points to the kurnl fake-Stripe page instead of your configured checkout URL. If your provider has no external_checkout_url configured, the endpoint returns 503.

Error codes


GET /partner/external-checkout/sessions/

Returns the current state of a session, with the referenced plan, unit/building, and provider embedded for display on your checkout page. Auth: X-Webhook-Secret header.

Response — 200 OK

expired and cancelled sessions are never returned as a body — they yield 410 Gone. The embedded units.buildings object carries the full postal address of the building the order is for — street, city, postal code, province and country. There is no buildings endpoint on the partner API, so this embed is the only place that address reaches you: read it from the session rather than expecting to look a building up by its id. The fields are nullable, because kurnl holds addresses for buildings at varying levels of completeness — render defensively. woocommerce_product_id is the intended product-mapping key for store integrations: set it on the plan version to join a kurnl plan to the product in your own catalog.
The TTL check runs before authentication by design — an expired session returns 410 even with a missing or wrong X-Webhook-Secret. It only ever applies to a session still in pending.

Error codes


PATCH /partner/external-checkout/sessions/

Upsell endpoint: swap the plan while the subscriber is still on your checkout page, or attach your own reference id. Only pending/redirected sessions are patchable. Auth: X-Webhook-Secret header.

Request body

Only these two fields are patchable — anything else (including unit_id, delivery_mode, service_provider_document_id) is rejected with 422.

Response — 200 OK

Returns the updated session object (same shape as GET).

Error codes