Ask for an invitation
Menu

Using the API

Errors

Every failure answers with an HTTP status of 400 or above and one error object. Branch on its code. This page has an entry for each of the 180 codes the API answers with, and it is where every doc_url points.

The error object

An order over a live business's tier limit, as the API answers it:

JSON

{
  "error": {
    "type": "limit_error",
    "code": "tier_order_limit",
    "message": "This order is US$1,250.00. The Unverified tier allows US$1,000.00 per order. Verify the business to raise the limit.",
    "limit": "single_order",
    "doc_url": "https://merchant.orrerie.com/docs/errors#tier_order_limit",
    "request_id": "req_c454pdhvpfr55c7br4jvzqep"
  }
}

limit names the limit that was reached: single_order (US$1,000 on the Unverified tier, US$50,000 for a Verified business) or first_orders (an Unverified business's first three paid orders may be at most US$250 each). Tier limits hold in live mode; a test order is not held to them.

Table: The error object
FieldAlways presentMeaning
typeYesThe family. One of invalid_request_error, authentication_error, permission_error, not_found_error, idempotency_error, state_error, limit_error, rate_limit_error, provider_error, api_error.
codeYesThe exact reason, from the table below. Branch on this.
messageYesA sentence for a developer. It may be reworded at any time: never parse it, never show it to a payer.
paramWhen one parameter is at faultDotted path: line_items[0].quantity.
doc_urlYeshttps://merchant.orrerie.com/docs/errors#<code>.
request_idYesSame as the Orrerie-Request-Id header.
extra fieldsPer codeFor example limit, available, needed, usable_at, retry_after, reason, available_assets, refundable, scope, instruction, errors[] (batch rows). Each is named in the table.

A rail failure shows the rule that nothing is ever switched silently. Nothing was created, and the payer can choose one of available_assets:

JSON

{
  "error": {
    "type": "provider_error",
    "code": "rail_unavailable",
    "message": "Relay cannot take USDT on TRON right now (relay_unavailable: the routing service did not answer). Nothing was created and nothing was switched. The payer can choose one of available_assets.",
    "param": "asset",
    "rail": "relay",
    "reason": "relay_unavailable",
    "available_assets": [
      "ethereum:usdc",
      "base:usdc",
      "bitcoin:btc",
      "litecoin:ltc"
    ],
    "doc_url": "https://merchant.orrerie.com/docs/errors#rail_unavailable",
    "request_id": "req_c454pdhvpfr55c7br4jvzqep"
  }
}

How to react, by family

Table: How to react, by family
FamilyHTTPRetry?
invalid_request_error, not_found_error400, 404, 405, 413, 415No. Fix the request.
authentication_error, permission_error401, 403No. Fix the key, its scopes, or do the action in the dashboard.
idempotency_error400, 409, 422409: yes, after Retry-After. Others: no.
state_error409Not as is. Read the object, then decide.
limit_error403Not until the limit moves (time passes, or the merchant verifies).
rate_limit_error429Yes, after Retry-After.
provider_error502, 503Yes, with backoff and the same idempotency key. For rail_unavailable, offer the payer available_assets instead.
api_error500, 503, 504Yes, with backoff (1 s, 2 s, 4 s, up to 5 tries) and the same idempotency key.

Every error code

Each code below is an anchor: https://merchant.orrerie.com/docs/errors#order_not_open lands on order_not_open. These are the 103 codes of the API's design; the codes this release adds follow them.

authentication_error

Retry? No. Fix the key, its scopes, or do the action in the dashboard.

Error codes of the family authentication_error
CodeHTTPMeaning
api_key_missing401No Authorization: Bearer header.
api_key_invalid401The key is not one Orrerie issued, or is malformed.
api_key_revoked401The key was revoked or its roll window ended.
api_key_expired401The key passed its expires_at.
secret_key_in_browser403A secret key arrived with an Origin header. Secret keys are for servers; the key is flagged in the dashboard and the Owners are emailed.

permission_error

Retry? No. Fix the key, its scopes, or do the action in the dashboard.

Error codes of the family permission_error
CodeHTTPMeaning
ip_not_allowed403The caller's IP address is not in the key's allowed_ips.
insufficient_scope403The key lacks the scope the endpoint needs; error.scope names it.
publishable_key_not_allowed403The endpoint, or a parameter sent, cannot be used with a pk_ key.
passkey_approval_required403The action can only be done by a signed-in member in the dashboard (settlement asset, key-holding roles, approvals). No API key can do it.
merchant_restricted403The merchant is restricted: new orders, payouts to others and conversions are off. Reads and withdrawals to saved addresses work.
test_helper_in_live_mode403A /v1/test/... endpoint was called with a live key.
destination_blocked403The destination address is on a sanctions list. The request is refused and recorded.

limit_error

Retry? Not until the limit moves (time passes, or the merchant verifies).

Error codes of the family limit_error
CodeHTTPMeaning
verification_required403The feature or value needs the Verified tier.
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.").
own_limit_reached403A withdrawal to the merchant's own saved address would pass the merchant's own safety limit for the last 24 hours (default US$10,000 Unverified, US$100,000 Verified).
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.
tier_open_orders_limit40350 (Unverified) or 2,000 (Verified) unpaid orders are open. Cancel or let some expire.
payout_daily_limit_reached403Payouts to others in the last 24 hours (payouts, split legs and refunds to a saved address) plus this one would pass US$1,000 (Unverified) or US$100,000 (Verified). Withdrawals to own saved addresses have no tier limit.
payout_batch_not_allowed403Batches need the Verified tier.
member_limit_reached4032 (Unverified) or 25 (Verified) members, counting pending invitations.
key_limit_reached4032 (Unverified) or 20 (Verified) live keys. Test keys: 20 in either tier.
webhook_endpoint_limit_reached4031 (Unverified) or 10 (Verified) endpoints per mode.

invalid_request_error

Retry? No. Fix the request.

Error codes of the family invalid_request_error
CodeHTTPMeaning
invalid_json400The body is not valid JSON, or not a JSON object.
unsupported_media_type415The body is not application/json (or multipart/form-data for a file upload).
request_too_large413The body is over 256 KB (5 MB for a file upload).
method_not_allowed405The path exists but not with this method.
route_not_found404No such path.
version_unsupported400The Orrerie-Version header names a version that does not exist or was retired.
parameter_missing400A required parameter is absent; error.param names it.
parameter_invalid400A parameter has the wrong type, format or range; error.param names it.
parameter_unknown400A parameter the endpoint does not take was sent. Unknown parameters are refused, not ignored, so that a typo cannot silently drop a field.
parameters_exclusive400Two parameters that cannot be combined were sent (for example amount and line_items).
metadata_invalid400More than 50 keys, a key over 40 characters, a value over 500 characters, or a non-string value.
url_invalid400Not https, has credentials, is over 2,048 characters, or (webhooks) resolves to a private address.
amount_invalid400Not a decimal string, negative, zero, or more decimal places than the currency has.
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.
currency_unsupported400Not a pricing currency the platform has a rate for.
asset_unsupported400Not an asset id from GET /v1/assets, or not usable for this purpose.
asset_not_enabled400The asset exists but is not switched on for this merchant.
settlement_invalid400settle names something that cannot be a settlement asset for this merchant.
destination_invalid400The address fails the network's format or checksum, or does not match the asset's network.
event_type_unknown400An entry of enabled_events is not an event type.
file_type_not_allowed400The upload is not PNG, JPEG, WebP or PDF, or its content does not match its type.
file_too_large413The upload is over 5 MB.
simulation_invalid400The test scenario cannot apply to the object in its present state.
livemode_mismatch400An id of the other mode was used: a test key naming a live object or the reverse.
rail_not_allowed400The rail is off for this order, merchant or asset (for example relay for Litecoin).
split_rule_invalid400Shares total more than 100%, a share is not above zero, a saved address is not active or not of kind other, or the scope object does not exist.
payout_batch_too_large400More than 200 rows, or more than 50 rows sent from one EVM network.
export_too_large400The filters match more than 500,000 rows. Narrow the dates.

not_found_error

Retry? No. Fix the request.

Error codes of the family not_found_error
CodeHTTPMeaning
resource_missing404No object with that id belongs to this merchant in this mode.

idempotency_error

Retry? 409: yes, after Retry-After. Others: no.

Error codes of the family idempotency_error
CodeHTTPMeaning
idempotency_key_required400The endpoint moves money on approval (refunds, payouts, batches, conversions, saved addresses) and needs an Idempotency-Key.
idempotency_key_invalid400The key is empty, over 255 characters or has characters outside printable ASCII.
idempotency_key_reused422The key was already used with a different method, path or body.
request_in_progress409The first request with this key is still running. Retry after Retry-After seconds.

state_error

Retry? Not as is. Read the object, then decide.

Error codes of the family state_error
CodeHTTPMeaning
order_not_open409The order is not open (or underpaid, for a top-up instruction).
order_not_payable409The order is cancelled, or already paid/overpaid.
order_not_underpaid409Only an underpaid order can be accepted as paid.
order_not_overpaid409Only an overpaid order with an unresolved excess has an overpayment to keep.
order_not_refundable409The order has nothing paid, or everything paid is already refunded or in a refund request.
instruction_in_flight409A payment for this order is on its way (an instruction is detected). Wait for it to settle, then refund if needed.
order_has_payment409The order has a payment, so it cannot be cancelled or voided. Refund it instead.
instruction_limit_reached409The order has had 20 payment instructions, the most allowed. Create a new order.
money_out_not_draft409Only a draft whose approval lapsed can be submitted again.
instruction_live409The order already has a live instruction on another asset; error.instruction is its id.
session_not_open409The checkout session is completed or expired.
customer_required409The action needs the order to have a customer.
customer_email_required409The customer or order has no email address.
customer_has_active_subscription409Cancel the customer's subscriptions first.
member_exists409That email is already a member or has a pending invitation.
invoice_not_draft409Only a draft invoice can be finalized or deleted.
invoice_not_open409Only an open invoice can be sent or voided.
invoice_not_editable409The field cannot change in the invoice's present state.
price_not_recurring409A subscription item names a one_time price, or items mix intervals or currencies.
price_inactive409The price or its product is archived.
subscription_not_active409Only an active or past_due subscription can be paused.
subscription_not_paused409Only a paused subscription can be resumed.
payment_not_unmatched409The payment already belongs to an order.
refund_amount_exceeds_refundable409More than amount_paid minus refunds confirmed or in request; error.refundable gives the figure.
money_out_not_cancellable409The request is signed or later. A signed transaction cannot be withdrawn.
saved_address_not_usable409The saved address is awaiting_approval, waiting (error.usable_at says until when) or removed.
insufficient_balance409The available balance (amount minus reserved) of the source asset is too low; error.available gives it.
fee_account_low409The fee account cannot pay the network fee. error.needed says how much of which coin on which network must be held, for example {"asset": "tron:trx", "amount": "30"}.
conversion_no_route409The chosen venue has no route for this pair or amount now. error.offers_url lists what every venue says.
quote_expired409The quote behind the request passed its 15 minutes.
webhook_endpoint_disabled409Re-enable the endpoint before resending to it.
event_expired409The event is older than 30 days.
file_in_use409The file is a logo, product image or attachment in use, or was generated by the platform.
wallet_not_activated409The order would settle in, or be paid directly to, a Solana or TRON wallet that is not yet activated. Until activation that wallet is behind one key, so it is not used. error.wallet is its id; activate it in the dashboard.
refund_wallet_not_protected409The payer chose Solana or TRON, the merchant's wallet there is not activated, and it already holds more than its cap (US$20 on Solana, the value of 100 TRX on TRON). No further instruction with that payer network is issued until the wallet is activated.
browser_key_backup_required409Live mode only: the merchant has not saved its browser key backup, so live orders cannot be created yet.

rate_limit_error

Retry? Yes, after Retry-After.

Error codes of the family rate_limit_error
CodeHTTPMeaning
export_limit_reached429More than 10 exports in an hour.
email_limit_reached429More than 5 sends of the same invoice or receipt in 24 hours.
rate_limit_exceeded429Too many requests. Wait Retry-After seconds.

provider_error

Retry? Yes, with backoff and the same idempotency key. For rail_unavailable, offer the payer available_assets instead.

Error codes of the family provider_error
CodeHTTPMeaning
screening_unavailable503The sanctions check could not be made. A failed check is never treated as clean; retry later.
rail_unavailable503The rail cannot be used now. error.reason is the exact refusal: relay_unavailable, relay_no_route, relay_amount_too_low, relay_low_liquidity, relay_paused, route_fee_over_cap, provider_route_mismatch, provider_deposit_mismatch, refund_wallet_unavailable, recipient_not_attested, or asset_not_covered; error.available_assets lists what can be used instead. Nothing was created at the provider and nothing was switched.
price_unavailable503No fresh price for the asset or currency. A stale price is never used for a quote.
provider_error502An outside service answered wrongly. No provider record was left half-made; safe to retry with the same idempotency key.

api_error

Retry? Yes, with backoff (1 s, 2 s, 4 s, up to 5 tries) and the same idempotency key.

Error codes of the family api_error
CodeHTTPMeaning
merchant_worker_waking503The merchant's own server process was asleep and is starting. Retry after Retry-After (2 seconds).
outcome_unknown504The request may or may not have taken effect (the engine's instruction_unknown for a payment instruction). Retry with the same idempotency key; never with a new one. For an instruction: show the payer nothing until it resolves.
service_unavailable503The API is briefly unavailable (deploy or overload). Retry with backoff.
internal_error500A fault on Orrerie's side. Quote request_id to support.

Codes this release adds

The API also answers with these 77 codes. A new code is not a breaking change: a program that meets a code it does not know reacts by its type and HTTP status, as the table by family says. Many of them come from steps a signed-in member takes in the dashboard, such as approving money out or moving a payment to another order; the API answers with the same code when a call meets the same state.

invalid_request_error

Retry? No. Fix the request.

Error codes of the family invalid_request_error that this release adds
CodeHTTPMeaning
https_required400The request did not arrive over HTTPS. Nothing was done; a key sent in the clear should be rolled.
accent_too_dark400The accent colour does not reach a contrast of 4.5:1 against the checkout's dark field, or no text colour reads on it at 4.5:1; see reason. Choose a lighter colour. reason is field (the dark field) or ink (the text on it); the dashboard checks the same rule while you type.
accepted_assets_empty400The change would switch off every way to pay. Keep at least one accepted asset switched on.
batch_network_required400The rows of the batch that wait for approval are on more than one network, so the network to approve must be named.
payout_batch_invalid400A payout batch has rows that cannot be paid. errors lists each bad row with its own code, and nothing of the batch was created.
target_same_order400A payment can be moved only to another order, never to the order it is on.

authentication_error

Retry? No. Fix the key, its scopes, or do the action in the dashboard.

Error codes of the family authentication_error that this release adds
CodeHTTPMeaning
secret_scanning_signature_invalid401Answered only on POST /v1/_secret_scanning, which GitHub's secret scanning partner programme calls when it finds an Orrerie secret key in public code. The report is not signed by a GitHub key Orrerie holds, so nothing was changed. Your own integration never calls this address.

permission_error

Retry? No. Fix the key, its scopes, or do the action in the dashboard.

Error codes of the family permission_error that this release adds
CodeHTTPMeaning
payer_email_off403Orrerie does not email payers in this release, so nothing was sent. Give the customer the link yourself; retrying does not change this. Answered by POST /v1/invoices/{id}/send, POST /v1/receipts/{id}/send and an invoice's finalize with send: true.
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.
app_pay_not_allowed403The business does not take payment through the Orrerie app, or the app did not say which account pays.

limit_error

Retry? Not until the limit moves (time passes, or the merchant verifies).

Error codes of the family limit_error that this release adds
CodeHTTPMeaning
file_limit_reached403The business has 500 stored pictures, the most it may have; see limit. Delete one it no longer uses first. A picture is deleted with DELETE /v1/files/{id}; uploading the same picture again answers the file already stored.
product_limit_reached403The account has 500 products that are not archived, or this product has 20 prices that are not archived; see reason and limit. Archive one first.

state_error

Retry? Not as is. Read the object, then decide.

Error codes of the family state_error that this release adds
CodeHTTPMeaning
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.
asset_not_available409The asset cannot be switched on, because no rail takes it now. The dashboard shows it as Not available yet.
order_has_instruction409The order already has payment details or a payment, so its amount or its periods can no longer be changed.
subscription_ended409The subscription has ended, ends at the close of this period, or has no period left, so this change can no longer be made.
check_window_closed409An address can be checked again for 12 months after its payment instruction expired, and that time has passed.
rail_not_direct409For this order the asset is not paid on the direct rail; rail names the rail it is paid on. Nothing was created.
rail_not_relay409For this order the asset is not paid on the relay rail; rail names the rail it is paid on. Nothing was created.
wallet_not_active409The wallet this needs is not in force: the business has not made its wallets yet, or the wallet on that network is not the one the request was made with. Nothing was done.
wallet_needs_review409The wallet holds less than Orrerie's records show, because money left it that nothing recorded. Money out from it waits until an Owner has reviewed the wallet in the dashboard.
owner_change_pending409A change of the business's keys is waiting or finishing, so this cannot be approved now; reason names the case. Payouts to anyone else wait until the change has ended. Withdrawals to the business's own saved addresses still go ahead.
retention_hold409A legal hold keeps this business's records, so nothing can be erased or merged while it lasts.
refund_open409The order has a refund that has not ended, so the payer's data cannot be erased yet. Retry once the refund has ended.
screening_pending409A live payment of the order is still waiting for its payer's screening, so the payer's data cannot be erased yet. Retry once the check has a result.
balance_changed409The balance moved after the amount was worked out, so the amount no longer holds. Ask again for a fresh one.
payment_not_confirmed409The payment is still confirming. It can be sent back once it is confirmed.
payer_wallet_unknown409The refund was asked to go back to the payer's Orrerie wallet, but the order has no record of one on this network, or the refund is more than that wallet paid. Refund to an address, or by a claim link, instead.
refund_source_not_supported409Money that Relay returned can be paid back from another balance only from the order's settlement asset, and not when the order keeps what was paid.
refund_rate_basis_unavailable409The order's own rate exists only for an asset the order was settled in. From this balance a refund can be paid only at today's value: send rate_basis today.
refund_not_approvable_yet409The refund goes to an address that was not saved before, so it waits 24 hours after the Owners were told; approvable_at says when it can be approved.
waiting_notice409The wait has not started, because the notice email to the Owners is not out yet. It can be approved once approvable_at is set and reached.
refund_not_awaiting_address409The refund no longer waits for the payer's address; state says where it is.
refund_not_routed409The refund is not sent through Relay, so it has no route to read or renew.
payout_not_routed409The payout is not sent through Relay, so it has no route to read or renew.
payout_in_batch409The payout is a row of a batch. It is approved with its batch, never alone.
split_leg_held409This share of a split payment is held, so it cannot be approved until the hold ends.
split_order_not_paid409The order this share of a split payment comes from is no longer paid, so the share cannot be paid out.
approval_document_unsupported409This release cannot prepare the approval for what was asked, so nothing is offered for signing; reason says why. Ask for it in parts.
money_out_not_signable409The refund, payout, conversion or sweep no longer waits for approval, so it cannot be signed; state says where it is.
money_out_not_signed409The money-out has not been signed, so it cannot be sent; state says where it is.
money_out_not_lapsable409Only a money-out that waits for approval can lapse, and this one does not wait; state says where it is.
conversion_not_prepared409The conversion has no order at its venue yet, so it cannot be approved. Ask for a new conversion.
relay_delivery_expired409Relay's quote for this delivery has expired; expired_at says when. Ask for a new one.
relay_delivery_not_prepared409The delivery through Relay has no address yet, or its address or amount is not the one quoted. Ask for a new quote.
sweep_not_offered409Combining small coins is not offered on this wallet now; reason says why.
sweep_in_progress409The wallet is already combining its small coins. Wait for that to end.
sweep_inputs_changed409The coins to combine changed after the sweep was prepared; changed says how many. Prepare it again.
screening_not_in_review409The order's payer is not waiting for a screening decision, so there is nothing to decide; status says where it stands.
screening_blocked409The payer's address was blocked by screening, so this cannot go ahead.
customer_credit_currency_mismatch409The customer's credit is held in another currency, so it cannot be used here.
customer_credit_insufficient409The customer holds less credit than was asked; available says how much, in minor units.
invoice_credit_already_applied409Credit was already applied to this invoice.
payment_being_matched409The payment arrived and is still being matched to an order, so nothing can be decided on it yet.
payment_being_refunded409The payment is being sent back.
payment_reverted409The payment is no longer on its network.
provider_refund_not_held409Nothing that Relay returned for this payment is still held.
provider_refund_proof_missing409The transfer Relay returned cannot be read right now. Retry later.
order_not_paid_twice409The order has no second payment to move.
payment_not_on_order409The payment is no longer on this order.
payment_not_second409Only the newest payment of an order paid twice can be moved.
payment_already_decided409Part of the extra on this order was already refunded or kept. Decide the rest on the order.
order_has_refunds409The order has a refund, so no payment can leave it.
payment_not_movable409The payment cannot be moved. Refund it, or keep it as customer credit.
payment_shared_out409Shares of this payment were already paid out under a split rule, so it cannot be moved. Refund it, or keep it as customer credit.
payment_under_review409The paying address is flagged for review. Decide that first.
order_would_not_stay_paid409Without this payment the order would no longer be paid, so the payment cannot be moved.
target_other_customer409A payment can be moved only to an open order of the same customer.
target_currency_mismatch409A payment can be moved only to an order priced in the same currency.
target_not_open409A payment can be moved only to an order that is still open.
target_expired409The order chosen has run out of time. Choose an order that is still open.

api_error

Retry? Yes, with backoff (1 s, 2 s, 4 s, up to 5 tries) and the same idempotency key.

Error codes of the family api_error that this release adds
CodeHTTPMeaning
cosigner_unavailable503Orrerie's co-signer is not available, so nothing that needs its signature was done. Receiving payments is unaffected. Retry later; retry_after, when sent, says when.