BillOS v1
Console llms.txt OpenAPI

AI agents: build on BillOS with Claude Code, Cursor or Codex

This section is for the case where the developer is an agent, or works beside one. An agent can do everything here by itself except one thing, on purpose: a person approves the sandbox key, once.

Start: one approval, then no human in the loop

npx billos sandbox --json     # → {"status":"authorization_required","verifyUrl":"…","userCode":"KQ7M-2XHD", …}
# show verifyUrl to the user and wait for them to approve, then:
npx billos sandbox --json     # → {"status":"approved","keyPrefix":"bk_test_3QfT","saved":true, …}

Or over HTTP, with no tooling: POST https://api.billos.co.il/v1/sandboxes, then poll POST https://api.billos.co.il/v1/sandboxes/token with the deviceCode (section 10). Show the user verifyUrl exactly as it was returned and wait: they sign in to BillOS and approve; do not try to open or complete it yourself. The key that arrives is a sandbox key on their account, where nothing is signed and nothing reaches the tax authority. Put it in the environment as BILLOS_API_KEY, never in source. Nothing else needs a person until going live.

npx billos init prepares a repository for agents: an MCP entry for Claude Code, Cursor and Codex that reads the key from the environment, a short AGENTS.md block and a Cursor rule holding the rules below, and BILLOS_API_KEY= in .env.example.

The same rules as an installable kit, with three example apps (Express, Next.js, Flask) that validate, issue, settle, credit and verify webhooks: github.com/billos-dev/billos. It holds an Agent Skill (npx skills add billos-dev/billos --skill billos) and a Claude Code plugin (/plugin marketplace add billos-dev/billos).

What to read

/llms.txtThe index: every page, each with a markdown twin
/llms-full.txtThe whole documentation in one file
any page + .md, or Accept: text/markdownThat page as markdown
/openapi.jsonOpenAPI 3.1, with a request example on every operation and the error shape on every refusal
/search?q=…Section search as JSON (the MCP tool search_docs is the same search)
/errorsEvery reason, and what to do about it

The rules an integration gets wrong

  1. Money is integer agorot. ₪354.00 is 35400. No floats, anywhere.
  2. Prices that include VAT need priceMode: "gross", with the gross amount in unitPriceExVat. Without it the price is read as before VAT and 18% is added on top.
  3. Issuing is permanent. A number is taken and never reused; an issued document cannot be edited or deleted. Call validate first, and correct only with credit-note.
  4. Send Idempotency-Key on every create, derived from your own order id. A retry then returns the same row instead of a second document.
  5. docType is a numeric code: 300 proforma, 305 tax invoice, 320 invoice-receipt, 330 credit note (never created directly), 400 receipt. A patur business issues 400 and 300 only.
  6. Payments must equal the total on a 320 and a 400, to the agora.
  7. Check X-BillOS-Mode on the first response: sandbox or live. A test key cannot see live businesses and the reverse.
  8. The key is server-side only. Never in a browser bundle or a mobile app.
  9. On an error, read hint. Branch on reason; retry only when retryable is true, and with the same idempotency key.
  10. Verify webhooks on the raw body (section 11), before parsing it.

Which door