BillOS v1
Console llms.txt OpenAPI
POST/sandboxes

Ask for a sandbox key

POST /sandboxes

Takes no credential: it is how a script, a CLI or a coding agent that holds no key yet asks for one.

A person approves. The answer is 202 with status: "authorization_required": a verifyUrl to show the person you are working for, and a deviceCode to keep. They open the link, a page of its own that says who is asking, sign in and approve or decline (no phone number and no enrolment: the sign-in is enough for a test key). Poll POST /sandboxes/token with the deviceCode every interval seconds; it answers pending until they approve and then hands over the key, once. The key is an ordinary sandbox key on their developer account: no expiry, visible and revocable in the console, and capped at 5,000 requests a day until the account verifies a phone. An authorization lives ten minutes.

Anonymous sandboxes are a server option that is off by default. Where the operator enabled them the answer is 201 with status: "ready" and an apiKey at once, for a sandbox nobody owns yet: it has small limits, expires at expiresAt, may not register webhooks or Connect apps or have documents read, and a person keeps it by opening claimUrl, which replaces its key. Read status and handle both.

Body (optional)

FieldTypeDescription
namestringWhat you are building, shown to the person on the approval screen. Letters, digits, space, dot, dash; 60 characters.

Response

201: { "ok": true, … }

FieldTypeDescription
okbooleanrequired
statusstringrequiredOne of: ready.
modestringrequiredOne of: sandbox.
apiKeystringrequiredThe bk_test_ key. Shown here once: send it as X-Api-Key.
keyPrefixstringThe first characters of the key, as the console lists it.
expiresAtstringrequiredWhen the key stops working unless the sandbox is claimed.
claimUrlstringA person opens it and signs in to keep the sandbox. Claiming replaces the key.
claimTokenstringThe token inside claimUrl.
limitsobject
limits.ratePerMinintegerRequests per minute while unclaimed.
limits.dailyCapintegerRequests per day while unclaimed.
apiBasestringThe base URL for every other call.
mcpUrlstringThe MCP endpoint, which takes the same key.
docsstringThe documentation index for agents.
nextarray of stringWhat to do with the key, in order.

Errors: 429, 503. Every failure answers { "error", "reason", "hint", "param", "doc_url", "retryable", "request_id" }: branch on reason, and read hint for what to change (https://docs.billos.co.il/errors.md).

POST /sandboxes
curl -X POST "$BASE/sandboxes" \
const res = await fetch(`${BASE}/sandboxes`, {
  method: 'POST',
  headers: {
  },
})
const data = await res.json()
if (!data.ok) throw new Error(data.reason)
import requests
res = requests.post(
    f"{BASE}/sandboxes",
)
data = res.json()
Set BASE to https://api.billos.co.il/v1 and KEY to your bk_live_… key, or a bk_test_… key to run it against the sandbox.
Manage your businesses, keys and webhooks in the BillOS Console.