Create a channel merchant's checkout session
Call POST /api/checkout-sessions from the channel’s server. Authenticate with
the channel key as Authorization: Bearer sk_... and name the merchant
explicitly with X-Merchant-Id: <merchant_id>.
curl --request POST \ --url https://staging.api.maxanapay.com/api/checkout-sessions \ --header 'Authorization: Bearer sk_test_replace_me' \ --header 'X-Merchant-Id: b3f1c8de-7a20-4c55-9e64-1d8f2a6b40c7' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: order_1001_checkout' \ --data @request.json{ "amount": "49.95", "currency": "USD", "external_order_id": "order_1001", "description": "Order 1001", "success_url": "https://checkout.example.com/orders/order_1001/success", "cancel_url": "https://checkout.example.com/orders/order_1001/cart", "allowed_origins": ["https://checkout.example.com"]}{ "allowed_origins": ["https://checkout.example.com"], "amount": "49.95", "cancel_url": "https://checkout.example.com/orders/order_1001/cart", "checkout_session_id": "cs_00000000000000000000000000000000", "checkout_url": "https://staging.maxanapay.com/pay/cs_00000000000000000000000000000000", "currency": "USD", "description": "Order 1001", "embed_url": "https://staging.maxanapay.com/embed/cs_00000000000000000000000000000000", "environment": "test", "expires_at": "2099-01-01T00:30:00+00:00", "external_order_id": "order_1001", "id": "cs_00000000000000000000000000000000", "items": [], "merchant_name": "Example Store", "metadata": {}, "payment_provider": "ppcp", "shipping_address": null, "shipping_amount_cents": null, "status": "open", "success_url": "https://checkout.example.com/orders/order_1001/success"}This is where the credential models diverge. The same operation accepts a
direct merchant’s own key without the extra header, but a channel key represents
many merchants and cannot resolve one without X-Merchant-Id. Maxana verifies
that the selected merchant belongs to the calling channel.
Keep two identifiers from that response. checkout_session_id is what the
browser step mounts and what every webhook about this order carries.
external_order_id is the value you sent, echoed back and carried on the same
events, so a delivery resolves to your order without a lookup.
amount is not returned that way. The session holds the value rather than your
string, so "10.00" comes back as "10"; the "49.95" in the example above
survives unchanged only because it has no trailing zero to lose. Compare it as a
decimal, never as text. Amounts and
currencies
carries that rule and the currency codes this field accepts — every ISO 4217
code still in use, not a shorter list — and which of them a merchant can be paid
in. A PayPal
session whose currency is not the account’s primary settlement currency is
refused here at creation with 400; read the merchant’s paypal_primary_currency
from the onboarding status and open the session
in it.
The session also has a clock. It starts at creation rather than when the buyer
arrives, and expires_in_minutes sets it; how long a session
lasts covers the default, the
range, and how to choose against the page the buyer will be looking at.
Create the body from that merchant’s authoritative order record and use an
Idempotency-Key when retrying the same session-creation intent. Store the
returned session identifier with both your order and merchant record. Refer to
the shared checkout-session contract for fields and
limits.
The response says test, and the SDK wants sandbox
Section titled “The response says test, and the SDK wants sandbox”environment on the response is the credential’s environment, and it takes one
of test or live. The browser SDK’s environment option
is a different vocabulary and takes one of live or sandbox.
They are not interchangeable, and they share exactly one spelling — live —
which is what makes the other one easy to miss. Piping the session’s test into
the SDK option throws config_error before anything mounts. Select the SDK
environment from your own deployment configuration, not from a field in the
session.
Current limits
Section titled “Current limits”There is no merchant_id or channel_id field in the request body. Neither a
browser-supplied tenant identifier nor a body property can override credential
scope. The session is immutable; create another one when order facts change.
Continue to Add checkout to the merchant experience.