BillOS v1
Console llms.txt OpenAPI

Authentication

Every request carries your API key in the X-Api-Key header:

curl -H "X-Api-Key: bk_live_..." https://api.billos.co.il/v1/businesses/BID

> ocr is the one scope you are not given by default. Every receipt scan runs a billed AI call on our side (in the sandbox exactly as in live), so it is granted on request rather than bundled: ask from the console (מפתחות API → סריקת קבלות) and we enable it on both of your environments. Everything else is on your keys from the first minute.

Multi-tenant model

One API key owns many businesses. Each business is one Israeli dealer (עוסק), one of your end users. You create a business per user (section 4), and GET /businesses lists every business under your key; every other endpoint is nested under /businesses/:bid and only works for businesses your key created. A request for another key's business returns 404 (not 403: existence is not revealed).

Key rotation

A client can hold several keys, up to a ceiling of 10 active keys at once (rotation headroom, not a fleet; configurable per account if you genuinely need more). Minting and revoking are self-service from the console once your account is approved: sign in at dash.billos.co.il, pass the SMS check, and issue or kill a key yourself. To rotate: mint the successor, switch your deployment to it, revoke the predecessor. Nothing else under the client moves.

GET /keys lists every key under your client with its prefix, label, creation time and last use, and marks the one making the request, so a key you did not create is visible to you.

Two things a key can never do to itself, by design: mint and revoke. Those live behind your console session and its SMS check, because a leaked key that could issue its own successor would survive its own revocation. billos login (section 13) is the same rule from the terminal: the browser approves, the key is minted there.

Rate limit

60 requests per minute per key (sliding window). Exceeding it returns 429 {"reason":"rate_limited"} with a Retry-After header (seconds). Back off and retry. GET /usage?days=30 returns your own per-endpoint request and error counts, the first place to look when you are throttled or failing.

Behind that sit a few daily backstops, deliberately high enough that a working integration never meets them and low enough to bound a runaway loop or a leaked key. They apply to every account on every plan, and they answer limit_reached (429):

BackstopDefault
Documents opened per business, per day300
Expense rows opened per business, per day (uploads included)300
New businesses per API key, per day50
OCR scans per API key, per day200 (quota_exceeded)

These are not your plan's ceilings; those are the monthly numbers on the business object (section 4). If a legitimate workload needs more of either, tell us and we raise it on your account.