Checkout

Create a hosted pay-first checkout session for a cart of catalog products. ibakepro reprices the cart server-side, returns a hosted checkout URL, and creates the order only on payment success. An abandoned session never becomes an order.

This is the headless equivalent of the ibakepro storefront checkout. It reuses the same hosted page and the same mint path.

Checkout accepts both secret (ibp_sk_) and publishable (ibp_pk_) keys, answers OPTIONS preflights, and returns CORS headers (Access-Control-Allow-Origin: *) on every response including errors, so you can create a session straight from the browser with a publishable key.

How it works

  1. Build a cart of product_id + variant_id + choices from the Products catalog.
  2. POST /api/v2/checkout with those items. ibakepro reprices server-side (you do not send prices here - this is the server-authoritative path, unlike Orders).
  3. Redirect the shopper to the returned checkout_url. On that page they enter their contact details, pick a fulfilment method, choose a date and time slot, optionally apply a discount code, and pay (Stripe, PayPal including Venmo, or Square, depending on what the merchant has enabled).
  4. On payment success ibakepro mints the order, records the payment, and marks the session completed. The shopper stays on the hosted page and sees its confirmation state.

The session is the only artifact created at step 2. No order, no customer, and no payment record exist until the shopper pays.


POST/api/v2/checkout

Create a checkout session

Reprice a cart and create a hosted session. Returns the session id, the hosted checkout_url, an expiry, and the server-computed pricing.

Required scope: checkout:write (in the publishable allowlist)

Send an Idempotency-Key header so a retried network call reuses the same session. The same key with a different body returns 422 idempotency_key_reused; a retry while the first call is still running returns 409 request_in_flight. Keys are retained for 24 hours.

Request body

  • Name
    items
    Type
    array
    Description

    Required, at least one. Each item: product_id, optional variant_id (the product's size/variant id, defaults to none), quantity (defaults to 1), optional custom_field_values (an object keyed by custom-field definition id), and optional choices: [{ choice_id, selected_option_id }]. Every product is checked before pricing: an unknown id, a product whose status is not active, or one with storefrontEnabled: false returns 400. Repricing failures (invalid variant, unknown choice option) are collected and also returned as 400.

  • Name
    success_url
    Type
    string
    Description

    Optional. Must be an absolute http or https URL. See Return URLs - this is a link on the hosted page, not an automatic redirect.

  • Name
    cancel_url
    Type
    string
    Description

    Optional. Must be an absolute http or https URL.

Delivery details, time slots and discount codes are not accepted here. The session is priced as pickup with no discount, and the shopper resolves all three on the hosted page.

Response fields

  • Name
    session_id
    Type
    string
    Description

    The checkout session id. Always prefixed cs_ followed by 32 random bytes, base64url encoded.

  • Name
    checkout_url
    Type
    string
    Description

    The hosted page to redirect the shopper to, on the regional app host for the key's region ({app_host}/checkout/{session_id}).

  • Name
    expires_at
    Type
    string
    Description

    ISO 8601. Exactly one hour after creation.

  • Name
    pricing
    Type
    object
    Description

    Server-computed subtotal, tax, delivery_fee, total, currency (the merchant's configured currency). delivery_fee is always 0 at this point because the session is priced as pickup. Treat this as a quote for the cart contents, not the final amount charged: delivery can add to it and a discount code can reduce it on the hosted page.

Request

POST
/api/v2/checkout
curl -X POST https://au.api.ibakepro.com/api/v2/checkout \
  -H "Authorization: Bearer ibp_pk_live_au_ABC" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cart-9f3a" \
  -d '{
    "items": [
      { "product_id": "prod_ze9HI0w0LpVbemUI",
        "variant_id": "base", "quantity": 1,
        "choices": [
          { "choice_id": "cho_hoFEGdk3rJ2waVe3",
            "selected_option_id": "opt_JiK6AYdC3lARutKE" }
        ] }
    ],
    "success_url": "https://shop.example.com/thanks",
    "cancel_url": "https://shop.example.com/cart"
  }'

Response (201)

{
  "session_id": "cs_6JXKKFTPvP0ZyOT-YTeBgVcqfy5taB2CxA_wZGd7CEQ",
  "checkout_url": "https://au.app.ibakepro.com/checkout/cs_6JXKKFTPvP0ZyOT-YTeBgVcqfy5taB2CxA_wZGd7CEQ",
  "expires_at": "2026-06-09T05:25:29.969Z",
  "pricing": {
    "subtotal": 97.00,
    "tax": 9.70,
    "delivery_fee": 0,
    "total": 106.70,
    "currency": "AUD"
  }
}

Session lifetime and expiry

A session expires one hour after creation, and that expiry is enforced:

  • An unpaid session past expires_at cannot be loaded. The hosted page returns 404 with Invalid or expired portal link, the same response as an unknown token.
  • Every payment route resolves the session through the same gate and refuses an expired one, so no charge can be created against it.
  • A session that was already paid is exempt. It still mints its order and still renders its confirmation long after expires_at has passed.

An expired session cannot be revived or extended. A new session is the only way to price and pay for that cart again.

Return URLs

success_url and cancel_url are optional, and neither is an automatic redirect. The hosted page owns the full return flow: after a gateway redirect the shopper lands back on {checkout_url}?status=success or ?status=cancelled, and the page shows its own confirmation or a "payment cancelled" notice.

  • With a URL for the relevant outcome, the page additionally renders a single onward link in the merchant's button colours: "Return to store" on success, "Back to store" on cancel. The shopper chooses when to follow it.
  • Without one, no link is rendered and the shopper stays on the hosted confirmation. Nothing else changes.

Only absolute http and https URLs are stored and rendered; anything else is rejected at create.

Session states

A session doc moves open to minting to completed. minting is a short-lived claim held while the order is committed, so concurrent gateway callbacks cannot mint twice. Only open (and unexpired) sessions are payable; only completed sessions carry an orderId.

Subscribe to the order.created and payment.completed webhook events to know when a session converts to an order. There is no endpoint to read a session back.

Notes

  • This endpoint is server-authoritative: you send items, ibakepro computes the price. The trusted-pricing model, where the caller supplies unit_price and pricing.total, is Orders-only and secret-key only.
  • No order, customer or payment is created until the shopper pays. Abandoned sessions expire silently.
  • Which gateways appear on the hosted page depends on what the merchant has enabled in their dashboard.
  • The hosted page is served noindex, nofollow.