BillOS v1
Console llms.txt OpenAPI

Documents

A document may name an ad-hoc party inline (just {"name": "..."}), which is fine for walk-ins. For repeat customers create a party once and reference it, so the customer ledger stays coherent:

curl -X POST "$BASE/businesses/$BID/parties" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
  -d '{ "kind": "customer", "name": "דנה לוי", "phone": "0521111111", "email": "dana@example.com" }'
# → {"ok":true,"party":{"id":"...","key":"C00001",...}}

# list / update / record consent to digital documents:
curl -H "X-Api-Key: $KEY" "$BASE/businesses/$BID/parties?kind=customer"
curl -X PATCH "$BASE/businesses/$BID/parties/$PARTY_ID" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d '{"phone":"0529999999"}'
curl -X POST "$BASE/businesses/$BID/parties/$PARTY_ID/consent" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d '{"via":"checkout-checkbox"}'

kind: "customer" | "supplier" | "both". The consent endpoint timestamps the party's agreement to receive documents digitally (מסמכים ממוחשבים). Record it once per customer if you deliver PDFs instead of paper.

5.2 Create a draft: POST /businesses/:bid/documents

curl -X POST "$BASE/businesses/$BID/documents" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-8812" -d '{
  "docType": 320,
  "party": { "name": "דנה לוי", "phone": "0521111111" },
  "priceMode": "gross",
  "lines": [
    { "description": "איפור כלה", "quantity": 1, "unitPriceExVat": 120000 },
    { "description": "איפור מלווה", "quantity": 2, "unitPriceExVat": 35000 }
  ],
  "payments": [ { "method": 3, "amount": 190000 } ]
}'
# 201 → {"ok":true,"document":{"id":"...","status":"draft","docNumber":null,...}}
FieldNotes
docType305 / 320 / 400 (330 only via the credit-note endpoint)
party{partyId} to reference a saved party, or inline {name, taxId?, phone?, email?, address?}; omit entirely for an anonymous cash receipt
linesRequired for 305/320: {description, quantity, unitPriceExVat}. Optional per line: sku, unit (default "יחידה"), lineDiscount (agorot)
priceMode"net" (the default: line prices are ex-VAT) or "gross": the same unitPriceExVat/lineDiscount fields carry VAT-inclusive amounts, the document total anchors to the gross sum and VAT is derived. Gross is what a consumer-facing price list wants: in the example above the customer pays exactly ₪1,900.00
paymentsRequired for 320/400: {method, amount} + optional {dueDate, bankCode, branchCode, accountNumber, checkNumber, cardCompany, cardName, cardTxType}
noteFree text (≤500 chars) printed on the document under the tables: remark, service context, terms. A credit note automatically carries its reason here
documentDate, valueDateDefault today (Asia/Jerusalem)
discountAmount, withholdingAmountDocument-level, agorot. Payments must cover the total net of withholding
externalRefIdempotency (or the Idempotency-Key header)

Payment method accepts a code or a string alias:

CodeAliasLabel on the PDF
1"cash"מזומן
2"check" / "cheque"המחאה
3"card" / "credit"כרטיס אשראי
4"transfer" / "bank_transfer"העברה בנקאית
5"voucher"תווי קניה
8"standing_order"הוראת קבע
9"other"אחר
91"bit"ביט
92"paybox"פייבוקס
93"payment_app" / "app"אפליקציית תשלום

Codes 91-93 are BillOS extensions so the printed document names the actual payment app; in the regulatory OPENFRMT export they are reported as 9 (אחר) per the ITA spec. Unknown values fall back to 9.

Drafts are freely mutable: they are a "קובץ זמני", not a tax document; any rendering of a draft is watermarked "טיוטה" and carries no number:

curl -X PATCH  "$BASE/businesses/$BID/documents/$DOC_ID" -H "X-Api-Key: $KEY" -H "Content-Type: application/json" -d '{"lines":[...]}'
curl -X DELETE "$BASE/businesses/$BID/documents/$DOC_ID" -H "X-Api-Key: $KEY"

5.3 List / read

curl -H "X-Api-Key: $KEY" "$BASE/businesses/$BID/documents?status=issued&docType=320&from=2026-07-01&to=2026-07-31"
curl -H "X-Api-Key: $KEY" "$BASE/businesses/$BID/documents/$DOC_ID"

5.3½ Preview a draft: POST /businesses/:bid/documents/:id/preview

Returns the draft rendered as a "טיוטה"-watermarked PDF (raw application/pdf bytes) so your user can see exactly how the document will look before the irreversible issue. Nothing is recorded and no number is consumed. Optional body {"branding": {...}} overrides the stored branding for this render. Drafts only: an issued document's PDFs are frozen; download those via prints (409 not_draft otherwise).

curl -X POST "$BASE/businesses/$BID/documents/$DOC_ID/preview" -H "X-Api-Key: $KEY" \
  -H "Content-Type: application/json" -d '{}' -o preview.pdf

5.4 Issue: POST /businesses/:bid/documents/:id/issue

The point of no return. Assigns the next gapless document number, freezes a full snapshot, renders the PDF and signs it digitally.

curl -X POST "$BASE/businesses/$BID/documents/$DOC_ID/issue" -H "X-Api-Key: $KEY"
# 201 → {"ok":true,"document":{"docNumber":1071,"status":"issued","totalIncVat":190000,"vatAmount":28983,...}}

5.5 Correct: POST /businesses/:bid/documents/:id/credit-note

The only way to "cancel" an issued 305/320. Issues a linked חשבונית מס זיכוי (330) mirroring the original amounts; for a receipt (400) it issues a negative receipt.

curl -X POST "$BASE/businesses/$BID/documents/$DOC_ID/credit-note" -H "X-Api-Key: $KEY" \
  -H "Content-Type: application/json" -d '{"reason":"הזמנה בוטלה"}'
# 201 → the new credit document, back-linked to the original

5.6 Get the PDF: POST /businesses/:bid/documents/:id/prints

Returns raw application/pdf bytes. kind is one of:

# a "download PDF" button can always just send auto:
curl -X POST "$BASE/businesses/$BID/documents/$DOC_ID/prints" -H "X-Api-Key: $KEY" \
  -H "Content-Type: application/json" -d '{"kind":"auto"}' -o invoice.pdf

409 {"reason":"pdf_pending"} → the PDF isn't rendered yet (rare, right after issue); retry with backoff; the origin is never consumed by a pdf_pending response. PDFs are PAdES-signed with a per-business certificate chained to the BillOS CA. Fetch the CA certificate at GET https://api.billos.co.il/ca.pem to verify signatures.

5.7 Allocation numbers (מספר הקצאה, חשבוניות ישראל)

Under the חשבוניות ישראל reform, a tax invoice (305/320) needs an allocation number from the Tax Authority when all of these hold: the amount before VAT exceeds the statutory threshold (₪5,000 since June 2026), the invoice carries VAT, and the buyer is an identified business, which needs the number to deduct input VAT. Credit notes (330) don't require one.

BillOS applies the same conditions at issue: by default it issues with an allocation_missing warning; if the business opts into strict mode (PATCH /businesses/:bid {"requireAllocation": true}), issue returns 422 allocation_required instead. Obtain the number (today: via the Tax Authority's website or your own ITA API integration) and supply it as allocationNumber on the draft, and it prints on the document under "מספר הקצאה". Most consumer-facing flows (B2C, receipts) never hit the threshold.