Sandbox and live
Sandbox and live are the same API on the same host, https://api.leeri.ai. The environment is chosen by the key you send: ak_sandbox_… keys run in sandbox, ak_live_… keys run live. To go to production you change the key and nothing else.
What differs
| Sandbox key | Live key | |
|---|---|---|
| Engine | The real screening engine, run against your own account's data | The same |
| Third-party data sources | Answered from stored answers only; a fresh lookup is never made | Fresh lookups when needed |
| Quota and balance | Never used | Used, see Rate limits and quotas |
| Rate ceiling | 10 requests per minute per route | 60 requests per minute per route |
Transaction check without address | Not allowed: ADDRESS_REQUIRED | Allowed for the assets that can derive it, see Supported assets |
Because sandbox never makes a fresh lookup, an address with no stored third-party answer is screened without one. The verdict then says so: it can be returned as partial, with the reason listed in partial_reasons. A live key looks the answer up.
Environments are separate
- A
check_id, batch id or verdict id created under one environment answers404 NOT_FOUNDunder the other, exactly like an id that does not exist. - Webhook endpoints belong to one environment and receive only that environment's events. Each environment can have up to 20 active endpoints; the 21st answers
400. Every delivery states which environment it came from in itsenvironmentfield. - Evidence reports carry the environment of the verdict they were issued for.
The test address
To exercise the pending path without waiting for a real slow lookup, submit this address under a sandbox key:
| Field | Value |
|---|---|
asset | BTC |
address | 1PENDNGCHECKADDRESSFRSANDBXTEST99 |
As an address check it always answers status: "pending" with a check_id, so you can build and test your polling and webhook handling on day one. The same address under a live key completes normally; the switch never fires outside sandbox.
- curl
- Node.js
- Python
curl -s -X POST https://api.leeri.ai/v1/checks \
-H "Authorization: Bearer $LEERI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"subject":"address","asset":"BTC","address":"1PENDNGCHECKADDRESSFRSANDBXTEST99"}'
const response = await fetch('https://api.leeri.ai/v1/checks', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LEERI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ subject: 'address', asset: 'BTC', address: '1PENDNGCHECKADDRESSFRSANDBXTEST99' }),
});
const { data } = await response.json();
console.log(data.status, data.check_id); // "pending" and the id to poll
import os
import requests
response = requests.post(
"https://api.leeri.ai/v1/checks",
headers={"Authorization": f"Bearer {os.environ['LEERI_API_KEY']}"},
json={"subject": "address", "asset": "BTC", "address": "1PENDNGCHECKADDRESSFRSANDBXTEST99"},
timeout=30,
)
data = response.json()["data"]
print(data["status"], data["check_id"]) # "pending" and the id to poll
Then poll GET /v1/checks/{check_id} until status leaves pending. Errors and limits are described in Errors.