Using the API
Authentication
Every call carries a key in the Authorization header. The key decides the mode, and no key of any kind can move money.
The three kinds of key
| Kind | Looks like | Where it may live | What it can do |
|---|---|---|---|
| Secret key | sk_live_ or sk_test_ + 43 base64url characters (256 random bits) | Your server only | Everything the API offers (scope *). Created only in the dashboard by an Owner, Admin or Developer. |
| Restricted key | The same prefix and length as a secret key; type: "restricted" on the key object | Your server only | Only the scopes you ticked. The recommended key for any integration. |
| Publishable key | pk_live_ or pk_test_ + 24 characters | A web page, an app | Create a checkout session from a payment link that allows it; read a session's status; read assets and rates. Nothing else. |
Send the key as Authorization: Bearer sk_. A key Orrerie did not issue, or one that is malformed (the placeholders on these pages among them), is refused with 401 api_key_invalid. A key in a query string or request body is refused and, because it has now been in a URL, should be rolled. Orrerie stores only the SHA-256 hash of a secret, so a lost secret cannot be shown again: roll the key.
Set the key in the environment of your server, never in code:
Shell
export ORRERIE_SECRET_KEY=sk_test_…The mode comes from the key: an sk_live_ key sees and creates only live objects, an sk_test_ key only test objects. Using an id from the other mode fails with livemode_mismatch. Test mode says what differs.
Owners, Admins and Developers manage keys in the dashboard. A live key is made and rolled only there, with a passkey: through the API, making or rolling a live key answers passkey_approval_required. A test key can make and roll test keys. A business on the Unverified tier may have 2 live keys, a Verified business 20; either may have 20 test keys. Every creation, roll and revocation is emailed to all Owners and written to the audit log.
What no key can do
No key of any kind can approve, sign or broadcast a transaction; add an active saved address; change the settlement asset, a rail, or the fee-bearer default; change an owner, a threshold, a passkey, or any member of the team (invitations, roles and removals are the dashboard's alone); or read or export any key material. In live mode no key makes or rolls a key, adds a webhook endpoint, moves one to another URL or rolls its signing secret, assigns an unmatched payment to an order, accepts an underpaid order as paid, or removes a saved address: the dashboard does these with a passkey. None is on the server to read: the browser key lives encrypted under the member's passkey. Where an endpoint exists at all, these answer passkey_approval_required.
The worst a stolen full secret key can do
It can read your data (orders, customers, balances), create orders and links, which bring money in, cancel unpaid orders, void invoices, and file refund and payout requests that then sit unapproved in the dashboard, where every Owner is emailed about them. It cannot take a cent. Restricting scopes and IP addresses narrows what it can read.
Scopes
A restricted key lists scopes of the form <resource>:read or <resource>:write. write includes read for the same resource. A call outside the key's scopes fails with insufficient_scope. Every endpoint page names the scope it needs.
| Scope | Covers |
|---|---|
checkout_sessions:read, checkout_sessions:write | Checkout sessions. |
orders:read, orders:write | Orders, payment options, payment instructions, receipts, POS device list. |
payments:read, payments:write | Payments; write is only assigning or ignoring an unmatched payment. |
products:read, products:write | Products and prices. |
payment_links:read, payment_links:write | Payment links. |
invoices:read, invoices:write | Invoices. |
customers:read, customers:write | Customers (personal data). |
subscriptions:read, subscriptions:write | Subscriptions. |
refunds:read, refunds:write | Refund requests. Write never moves money: it asks. |
payouts:read, payouts:write | Payout, withdrawal and batch requests; saved-address proposals. Write never moves money: it asks. |
conversions:read, conversions:write | Conversion offers and requests. |
wallets:read | Wallets, balances, fee account, ledger. There is no wallets:write. |
webhooks:read, webhooks:write | Webhook endpoints, delivery attempts, resends. |
events:read | Events. |
files:read, files:write | Files. |
exports:read, exports:write | Exports (can hold personal data). |
merchant:read, merchant:write | The merchant object; write is the public profile only. |
team:read, team:write | Members and invitations for roles without a wallet key. |
keys:read, keys:write | API keys. Only a full secret key or a restricted key given keys:write in the dashboard. |
GET /v1/assets and GET /v1/rates need no scope. Test-mode helper endpoints need the write scope of the object they act on.
A restricted key may also carry allowed_ips, up to 20 addresses or CIDR ranges; a call from elsewhere fails with ip_not_allowed.
A key never makes a key wider than itself. The new key's scopes must be ones the maker holds; if the maker has allowed_ips, the new key's list must lie inside it (the maker's list is used when you give none); if the maker has expires_at, the new key ends no later (the maker's end is used when you give none). A key rolls only keys inside those same bounds. Otherwise the call fails with parameter_invalid and reason wider_than_caller.
Rotation
- Roll a live key in the dashboard, or a test key with
POST /v1/keys/{id}/roll. It creates a replacement with the same name, scopes and IP list and returns its secret once. Sending the same request again with itsIdempotency-Keyreturns the key withoutsecret: a secret is never kept. The old key keeps working forexpires_inseconds (24 hours by default, at most 7 days, 0 for "now") withstatus: "rolling", then becomesrevoked. Deploy the new secret inside that window. - Revoke with
DELETE /v1/keys/{id}. It is immediate and permanent. Use it for a leak. - Expiry: a key may be created with
expires_at; after it the key answersapi_key_expired. - A key unused for 90 days is listed in the dashboard as "unused" with a one-click revoke. It is not revoked automatically, because a quarterly job may use it.
- Webhook signing secrets roll separately. See rolling a signing secret.