Endpoint
Create a checkout session
POST
/v1/checkout_sessionsCreates the session and, unless order is given, its order. With a publishable key only payment_link, quantity, amount (open-amount links), client_reference_id and customer_email are accepted, and the link must have allow_publishable_key: true.
- Scope a restricted key needs
checkout_sessions:write- Publishable key
- Allowed
- Idempotency-Key
- Recommended. It makes a retry safe.
Parameters
| Parameter | Type and place | Meaning |
|---|---|---|
Orrerie-Version | stringheader | API version date. Default: the version the key was created with. Example 2026-10-11. |
Idempotency-Key | stringheader | Makes a retry safe. Kept 24 hours. 1 to 255 characters. |
Request body
A JSON object. The body is required. A field the call does not list is refused with parameter_unknown.
| Field | Type | Meaning |
|---|---|---|
order | string | An existing open order to pay. If absent, give amount + currency or line_items and an order is created. |
amount | string | The price. Up to 2 decimals for fiat, up to the asset's decimals for a crypto pricing currency. Minimum the equivalent of US$1.00. Pattern ^\d+(\.\d+)?$. |
currency | string | Pricing currency: ISO 4217 code (USD) or asset id (bitcoin:btc). Required with amount. |
line_items | array of values | Up to 100 items, each {price, quantity} or {name, unit_. The order amount is their sum. Not allowed together with amount. |
description | string | Shown to the payer above the amount. Up to 500 characters. |
reference | string | Your order number. Up to 200 characters. |
customer | string | A cus_ id. It is kept with that customer. |
customer_email | string | Kept, encrypted, and returned as customer_email. No receipt is emailed in this release. |
success_url | string | HTTPS URL the payer is sent to after payment. May contain {CHECKOUT_SESSION_ID} and {ORDER_ID}. Required unless payment_link is given (the session then takes the link's). |
cancel_url | string | HTTPS URL behind the "Back to shop" link. |
client_reference_id | string | Echoed back on the session and in events. Up to 200 characters. |
collect | object | email, name, shipping_address: each required, optional or hidden. Default email required, others hidden. |
locale | string | auto (default) or en. |
expires_in | integer | Seconds the order stays payable: 900 to 604,800 (15 minutes to 7 days). Default the merchant setting (3,600). |
fee_bearer | string | Overrides the merchant default for this order. One of payer, merchant. |
rails_allowed | array of values | Subset of orrerie_app, relay, direct. Default: all the merchant has on. |
accept | array of values | Limit what the payer may pay with: asset ids and/or orrerie_app. Each must be switched on for the merchant (asset_not_enabled). Empty or absent: everything switched on. |
settle | string | default (the merchant's settlement asset), keep (keep what was paid, no conversion), or one of the merchant's allowed settlement asset ids. Resolved to the merchant's own wallet by the server and frozen on the order; a caller can never supply an address. |
mode | string | Default payment. subscription needs subscription_data. One of payment, subscription. |
subscription_data | object | {items: [{price, quantity}], grace_: creates the subscription when the first period is paid. |
metadata | object | Your own key-value data (rules in Metadata). |
payment_link | string | A plink_ id: the session takes its price, URLs and settings from the link. |
quantity | integer | With payment_link: the quantity, within the link's limits. |
Example request
curl
curl https://api.orrerie.com/v1/checkout_sessions \
-H "Authorization: Bearer $ORRERIE_SECRET_KEY" \
-H "Idempotency-Key: 8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a" \
-H "Content-Type: application/json" \
-d '{
"amount": "21.99",
"currency": "USD",
"description": "Order #1042",
"reference": "1042",
"customer_email": "jane@example.com",
"success_url": "https://acme.example/thanks?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://acme.example/cart",
"client_reference_id": "1042",
"metadata": {
"cart_id": "c_7781"
}
}'JavaScript
const response = await fetch("https://api.orrerie.com/v1/checkout_sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ORRERIE_SECRET_KEY}`,
"Idempotency-Key": "8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a",
"Content-Type": "application/json",
},
body: JSON.stringify({
"amount": "21.99",
"currency": "USD",
"description": "Order #1042",
"reference": "1042",
"customer_email": "jane@example.com",
"success_url": "https://acme.example/thanks?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://acme.example/cart",
"client_reference_id": "1042",
"metadata": {
"cart_id": "c_7781"
}
}),
});
const result = await response.json();
if (!response.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
console.log(result);Python
import os
import requests
response = requests.post(
"https://api.orrerie.com/v1/checkout_sessions",
headers={"Authorization": f"Bearer {os.environ['ORRERIE_SECRET_KEY']}", "Idempotency-Key": "8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a"},
json={
"amount": "21.99",
"currency": "USD",
"description": "Order #1042",
"reference": "1042",
"customer_email": "jane@example.com",
"success_url": "https://acme.example/thanks?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://acme.example/cart",
"client_reference_id": "1042",
"metadata": {
"cart_id": "c_7781",
},
},
timeout=30,
)
result = response.json()
if not response.ok:
raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}")
print(result)PHP
<?php
$request = curl_init('https://api.orrerie.com/v1/checkout_sessions');
curl_setopt_array($request, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('ORRERIE_SECRET_KEY'),
'Idempotency-Key: 8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => '21.99',
'currency' => 'USD',
'description' => 'Order #1042',
'reference' => '1042',
'customer_email' => 'jane@example.com',
'success_url' => 'https://acme.example/thanks?session={CHECKOUT_SESSION_ID}',
'cancel_url' => 'https://acme.example/cart',
'client_reference_id' => '1042',
'metadata' => [
'cart_id' => 'c_7781',
],
]),
]);
$body = curl_exec($request);
if ($body === false) {
throw new RuntimeException(curl_error($request));
}
$result = json_decode($body, true);
if (curl_getinfo($request, CURLINFO_HTTP_CODE) >= 400) {
throw new RuntimeException($result['error']['code'] . ': ' . $result['error']['message']);
}
print_r($result);Responses
201 Created
The answer is the checkout_session object. Headers: Orrerie-Request-Id.
Example response, 201
{
"id": "cs_z7ek5wj68fyz80j7bz1eq4e0",
"object": "checkout_session",
"livemode": true,
"created": "2026-10-11T14:03:22.418Z",
"status": "open",
"mode": "payment",
"order": "ord_0zymngngvf12b8b2cra7tb8e",
"url": "https://pay.orrerie.com/c/cs_z7ek5wj68fyz80j7bz1eq4e0",
"app_url": "https://pay.orrerie.com/o/cs_z7ek5wj68fyz80j7bz1eq4e0",
"success_url": "https://acme.example/thanks?session={CHECKOUT_SESSION_ID}",
"cancel_url": "https://acme.example/cart",
"customer": "cus_8ea07c40qsvv19f7rgmeb8ha",
"customer_email": "jane@example.com",
"client_reference_id": "1042",
"collect": {
"email": "required",
"name": "optional",
"shipping_address": "hidden"
},
"collected": {
"email": null,
"name": null,
"shipping_address": null
},
"locale": "auto",
"subscription": null,
"expires_at": "2026-10-11T15:03:22.418Z",
"completed_at": null,
"metadata": {
"cart_id": "c_7781"
}
}Any other status: an error
A status of 400 or above answers with the error object. Branch on its code, never on its message.
Errors
Beside the errors every call can answer with (a bad key, a missing scope, the rate limit), this call answers with:
| Code | HTTP | Meaning |
|---|---|---|
parameter_missing | 400 | A required parameter is absent; error.param names it. |
amount_below_minimum | 400 | Below the minimum: US$1.00 for an order payable on the relay rail, the network dust limit on the direct rail or for a payout. |
tier_order_limit | 403 | error.limit is single_order: over the tier's single-order maximum (US$1,000 Unverified, US$50,000 Verified). Or first_orders: an Unverified merchant's first three paid orders may be at most US$250 each ("Your first three orders can be up to US$250 each."). |
tier_open_orders_limit | 403 | 50 (Unverified) or 2,000 (Verified) unpaid orders are open. Cancel or let some expire. |
tier_volume_limit | 403 | error.window is 30_days: paid orders and unmatched payments you kept in the last 30 days, plus this one, would pass the tier limit (US$5,000 / US$250,000). Or lifetime: an Unverified merchant passed US$20,000 of such takings in total and must verify to create new orders. A reverted payment is taken back out. |
currency_unsupported | 400 | Not a pricing currency the platform has a rate for. |
price_unavailable | 503 | No fresh price for the asset or currency. A stale price is never used for a quote. |
asset_not_enabled | 400 | The asset exists but is not switched on for this merchant. |
settlement_invalid | 400 | settle names something that cannot be a settlement asset for this merchant. |
url_invalid | 400 | Not https, has credentials, is over 2,048 characters, or (webhooks) resolves to a private address. |
merchant_restricted | 403 | The merchant is restricted: new orders, payouts to others and conversions are off. Reads and withdrawals to saved addresses work. |
order_not_open | 409 | The order is not open (or underpaid, for a top-up instruction). |
support_email_required | 409 | The business has no support email yet, and no order can be created without one, in test mode too. A member adds it in the dashboard under Settings, Business profile, Support email; then retry. |
merchant_closing | 403 | The business is closing: new orders, payment links and invoices are off, and money goes out only to its own saved addresses. Reads, exports and withdrawals to saved addresses work until it closes. |
link_open_orders_limit | 409 | The payment link has 32 unpaid orders open, or has taken 240 orders in 24 hours, the most allowed. Open orders expire by themselves; retry later. |