Documents
5.1 Parties (customers): optional but recommended
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,...}}
| Field | Notes |
|---|---|
docType | 305 / 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 |
lines | Required 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 |
payments | Required for 320/400: {method, amount} + optional {dueDate, bankCode, branchCode, accountNumber, checkNumber, cardCompany, cardName, cardTxType} |
note | Free text (≤500 chars) printed on the document under the tables: remark, service context, terms. A credit note automatically carries its reason here |
documentDate, valueDate | Default today (Asia/Jerusalem) |
discountAmount, withholdingAmount | Document-level, agorot. Payments must cover the total net of withholding |
externalRef | Idempotency (or the Idempotency-Key header) |
Payment method accepts a code or a string alias:
| Code | Alias | Label 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,...}}
- Totals are recomputed server-side at issue from the frozen lines, so what you get back is authoritative.
- Issuing twice is safe: the second call returns the same document with
"deduped": true. - Optional body
{"branding": {...}}overrides the business's stored branding for this document only (same fields as the branding section above); omit it to use the stored defaults. - If PDF rendering hiccups, the document is still legally issued (numbering never rolls back); the PDF is rendered by a background retry, and
printsreturnspdf_pendinguntil it's ready.
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:
"auto": recommended. The origin (מקור) on the first ever print, a copy (העתק) on every print after; never errors on a repeat request. TheX-Print-Variantresponse header (origin|copy) says which one you got, so deliver anoriginstraight to the end customer."origin": explicitly the מקור. Succeeds exactly once per document; a second call returns400 {"error":"origin_already_printed"}."copy"(default): a העתק-watermarked copy, any number of times.
# 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.