Ask for an invitation
Menu

Endpoint

Create an order

POST/v1/orders

Creates an open order with no checkout session. Use it when you render your own payment page.

Scope a restricted key needs
orders:write
Publishable key
Not allowed: secret or restricted key only
Idempotency-Key
Recommended. It makes a retry safe.

Parameters

Parameters of Create an order
ParameterType and placeMeaning
Orrerie-VersionstringheaderAPI version date. Default: the version the key was created with. Example 2026-10-11.
Idempotency-KeystringheaderMakes a retry safe. Kept 24 hours. 1 to 255 characters.

Request body

A JSON object. The body may be left out. A field the call does not list is refused with parameter_unknown.

Request body of Create an order
FieldTypeMeaning
amountstringThe 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+)?$.
currencystringPricing currency: ISO 4217 code (USD) or asset id (bitcoin:btc). Required with amount.
line_itemsarray of valuesUp to 100 items, each {price, quantity} or {name, unit_amount, quantity}. The order amount is their sum. Not allowed together with amount.
descriptionstringShown to the payer above the amount. Up to 500 characters.
referencestringYour order number. Up to 200 characters.
customerstringA cus_ id. It is kept with that customer.
customer_emailstringKept, encrypted, and returned as customer_email. No receipt is emailed in this release.
expires_inintegerSeconds the order stays payable: 900 to 604,800 (15 minutes to 7 days). Default the merchant setting (3,600).
fee_bearerstringOverrides the merchant default for this order. One of payer, merchant.
rails_allowedarray of valuesSubset of orrerie_app, relay, direct. Default: all the merchant has on.
acceptarray of valuesLimit 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.
settlestringdefault (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.
metadataobjectYour own key-value data (rules in Metadata).

Example request

curl

curl https://api.orrerie.com/v1/orders \
  -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": "cus_8ea07c40qsvv19f7rgmeb8ha",
  "expires_in": 3600,
  "metadata": {
    "cart_id": "c_7781"
  }
}'

JavaScript

const response = await fetch("https://api.orrerie.com/v1/orders", {
  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": "cus_8ea07c40qsvv19f7rgmeb8ha",
    "expires_in": 3600,
    "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/orders",
    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": "cus_8ea07c40qsvv19f7rgmeb8ha",
        "expires_in": 3600,
        "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/orders');
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' => 'cus_8ea07c40qsvv19f7rgmeb8ha',
        'expires_in' => 3600,
        '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 order object. Headers: Orrerie-Request-Id.

Example response, 201

{
  "id": "ord_0zymngngvf12b8b2cra7tb8e",
  "object": "order",
  "livemode": true,
  "created": "2026-10-11T14:03:22.418Z",
  "updated": "2026-10-11T14:03:22.418Z",
  "status": "open",
  "source": "api",
  "amount": "21.99",
  "currency": "USD",
  "value": {
    "amount": "21.99",
    "currency": "USD"
  },
  "fx": null,
  "description": "Order #1042",
  "reference": "1042",
  "customer": "cus_8ea07c40qsvv19f7rgmeb8ha",
  "customer_email": "jane@example.com",
  "line_items": [
    {
      "name": "Ethiopia Yirgacheffe, 1 kg",
      "quantity": 1,
      "unit_amount": "21.99",
      "amount": "21.99",
      "price": "price_mbk5s5r45kwheaq89dbmk2gz"
    }
  ],
  "settlement": {
    "mode": "convert",
    "asset": "base:usdc",
    "amount_expected": "21.990000",
    "amount_received": null,
    "wallet": "wal_bsfw07hymawmda7gg8jsyy3g"
  },
  "fee_bearer": "payer",
  "amount_paid": "0.00",
  "amount_due": "21.99",
  "amount_refunded": "0.00",
  "paid_late": false,
  "accepted_short": false,
  "refunded": false,
  "partially_refunded": false,
  "finalized": true,
  "has_unconfirmed": false,
  "screening_hold": false,
  "screening": {
    "status": "clear"
  },
  "provider_refund_received": false,
  "overpayment": null,
  "rails_allowed": [
    "orrerie_app",
    "relay",
    "direct"
  ],
  "accept": [],
  "app_pay_allowed": true,
  "active_instruction": null,
  "instructions": [],
  "payments": [],
  "checkout_session": null,
  "payment_link": null,
  "invoice": null,
  "subscription": null,
  "pos_device": null,
  "receipt": null,
  "expires_at": "2026-10-11T15:03:22.418Z",
  "paid_at": null,
  "cancelled_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:

Errors of Create an order
CodeHTTPMeaning
amount_below_minimum400Below 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_limit403error.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_limit40350 (Unverified) or 2,000 (Verified) unpaid orders are open. Cancel or let some expire.
tier_volume_limit403error.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_unsupported400Not a pricing currency the platform has a rate for.
merchant_restricted403The merchant is restricted: new orders, payouts to others and conversions are off. Reads and withdrawals to saved addresses work.
support_email_required409The 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_closing403The 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.