Ask for an invitation
Menu

Start

Test mode

Test mode is the same API with simulated payments. The key decides the mode. No real money moves, and no payer is ever shown an address.

Live mode and test mode, side by side

Table: Live mode and test mode
Live modeTest mode
Keyssk_live_, pk_live_sk_test_, pk_test_
Objectslivemode: truelivemode: false, same id prefixes
MoneyReal, on the eleven networksNone. Payments are simulated.
WalletsThe merchant's eleven walletsThe same eleven are listed with livemode: false and address: null; balances are simulated and start at zero, growing as simulated payments settle
Addresses shown to a payerReal deposit addressesNone, ever. payment_instruction.address is null and test_simulation_url is set
Hosted checkoutThe real pageThe same page with a fixed banner "Test mode: no real payment is possible here." and, where the address and QR code would be, a "Test payment" panel with the buttons Pay in full, Underpay by 10%, Overpay by 10%, Pay late, Let it expire and Fail routing
ApprovalsPasskey in the dashboardNothing to sign: the dashboard shows "Approve (test)", or call the helper POST /v1/test/money_out/{id}/advance
EmailsSent only to your business's own members. Orrerie emails no customer in this release.Sent only to the merchant's own members, with "[TEST]" in the subject. A test-mode email never goes to a customer's address
WebhooksEndpoints added in the signed-in dashboard; a live key cannot add oneEndpoints created with a test key; signed the same way; 3 delivery attempts instead of 12
Tier limitsEnforcedNot enforced, except the rate limit and the counts of keys and endpoints
Data lifeKeptDeleted 90 days after creation; "Delete all test data" in the dashboard clears it at once

Test mode never shows an address

In test mode payment_instruction.address is null and test_simulation_url is set. There are no test-network wallets, so nobody can send real coins to an address that is only being watched on a test network.

What a test key cannot change

The account is one in both modes. A test key reads the merchant (with livemode: false), but the public profile (support email, logo, accent colour) is what live payers see, so only a live key or the dashboard changes it. A test key's PATCH /v1/merchant answers livemode_mismatch with reason live_profile and changes nothing.

What simulation covers

An exact payment, an underpayment, an overpayment, a late payment, a provider refund, a reverted payment and an unmatched payment, on any rail and asset. Each walks the real states and sends the real events with livemode: false. Subscriptions have a clock helper; refunds, payouts and conversions have an advance helper that can also end them failed or unknown.

curl

curl https://api.orrerie.com/v1/test/orders/ord_0zymngngvf12b8b2cra7tb8e/simulate_payment \
  -H "Authorization: Bearer $ORRERIE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "scenario": "exact",
  "asset": "ethereum:usdc"
}'

JavaScript

const response = await fetch("https://api.orrerie.com/v1/test/orders/ord_0zymngngvf12b8b2cra7tb8e/simulate_payment", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ORRERIE_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "scenario": "exact",
    "asset": "ethereum:usdc"
  }),
});
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/test/orders/ord_0zymngngvf12b8b2cra7tb8e/simulate_payment",
    headers={"Authorization": f"Bearer {os.environ['ORRERIE_SECRET_KEY']}"},
    json={
        "scenario": "exact",
        "asset": "ethereum:usdc",
    },
    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/test/orders/ord_0zymngngvf12b8b2cra7tb8e/simulate_payment');
curl_setopt_array($request, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('ORRERIE_SECRET_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'scenario' => 'exact',
        'asset' => 'ethereum:usdc',
    ]),
]);
$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);

The helper endpoints

These endpoints exist only for sk_test_ keys. With a live key they answer 403 with test_helper_in_live_mode.

Going live

Going live is changing the key. Objects do not move between modes: products, prices, links and webhook endpoints are created again with the live key.

Limits until your business is verified

Until your business is verified it is on the Unverified tier, with these limits:

  • Each of your first three paid orders can be up to US$250, and any later order up to US$1,000.
  • Paid orders and unmatched payments you keep may total US$5,000 in any 30 days and US$20,000 in all. Once that total is reached, new orders are refused until you verify the business in the dashboard.
  • At most 50 unpaid orders can be open at once.
  • Payouts to others are limited to US$1,000 in any 24 hours; withdrawals to your own saved addresses have no tier limit.

A Verified business can take orders of up to US$50,000, and US$250,000 in any 30 days with no total limit, and pay out up to US$100,000 in 24 hours. Over a limit the API answers 403 with tier_order_limit, tier_volume_limit, tier_open_orders_limit or payout_daily_limit_reached (see the limit errors). Test mode does not enforce these limits, so plan for them before your first real sale.