Issue documents from any system
The ChatInvoice API lets a website, shop, CRM or any other system issue legally valid Israeli accounting documents on behalf of a business — quotes, invoices, receipts and credit notes — with sequential numbering, a digitally signed PDF, a tax-authority allocation number when required, and delivery to the customer per the business settings.
https://api.chat-invoice.co.il/v1Authorization: Bearer ci_live_…YYYY-MM-DD (Israel time) · amounts in ILS, 2 decimals01Quick start
- Create a key in the app: Settings → Connections → API → “Create key”. It is shown once — store it server-side.
- Check the connection and see what the business may issue:
curl https://api.chat-invoice.co.il/v1/me -H "Authorization: Bearer $CHATINVOICE_API_KEY" - Issue a quote for a new customer:
curl -X POST https://api.chat-invoice.co.il/v1/documents \
-H "Authorization: Bearer $CHATINVOICE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-8812" \
-d '{"type":"quote","customer":{"name":"ישראל ישראלי בע\"מ","tax_id":"515123456","email":"billing@example.co.il","phone":"0501234567"},"items":[{"description":"הובלת דירה 4 חדרים","quantity":1,"unit_price":2500},{"description":"אריזה","quantity":10,"unit_price":45}],"title":"הצעה למעבר דירה","notes":"תוקף ההצעה 14 יום","external_ref":"crm-8812"}'const res = await fetch("https://api.chat-invoice.co.il/v1/documents", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.CHATINVOICE_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "crm-8812",
},
body: JSON.stringify({
"type": "quote",
"customer": {
"name": "ישראל ישראלי בע\"מ",
"tax_id": "515123456",
"email": "billing@example.co.il",
"phone": "0501234567"
},
"items": [
{
"description": "הובלת דירה 4 חדרים",
"quantity": 1,
"unit_price": 2500
},
{
"description": "אריזה",
"quantity": 10,
"unit_price": 45
}
],
"title": "הצעה למעבר דירה",
"notes": "תוקף ההצעה 14 יום",
"external_ref": "crm-8812"
}),
});
const doc = await res.json();
if (!res.ok) throw new Error(doc.error.code + ": " + doc.error.message);
console.log(doc.number, doc.view_url, doc.pdf_url);import os, requests
r = requests.post(
"https://api.chat-invoice.co.il/v1/documents",
headers={
"Authorization": f"Bearer {os.environ['CHATINVOICE_API_KEY']}",
"Idempotency-Key": "crm-8812",
},
json={
"type": "quote",
"customer": {
"name": "ישראל ישראלי בע\"מ",
"tax_id": "515123456",
"email": "billing@example.co.il",
"phone": "0501234567"
},
"items": [
{
"description": "הובלת דירה 4 חדרים",
"quantity": 1,
"unit_price": 2500
},
{
"description": "אריזה",
"quantity": 10,
"unit_price": 45
}
],
"title": "הצעה למעבר דירה",
"notes": "תוקף ההצעה 14 יום",
"external_ref": "crm-8812"
},
timeout=90,
)
doc = r.json()
if not r.ok:
raise RuntimeError(f"{doc['error']['code']}: {doc['error']['message']}")
print(doc["number"], doc["view_url"], doc["pdf_url"])$ch = curl_init("https://api.chat-invoice.co.il/v1/documents");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("CHATINVOICE_API_KEY"),
"Content-Type: application/json",
"Idempotency-Key: crm-8812",
],
CURLOPT_POSTFIELDS => json_encode([
"type" => "quote",
"customer" => [
"name" => "ישראל ישראלי בע\"מ",
"tax_id" => "515123456",
"email" => "billing@example.co.il",
"phone" => "0501234567"
],
"items" => [
[
"description" => "הובלת דירה 4 חדרים",
"quantity" => 1,
"unit_price" => 2500
],
[
"description" => "אריזה",
"quantity" => 10,
"unit_price" => 45
]
],
"title" => "הצעה למעבר דירה",
"notes" => "תוקף ההצעה 14 יום",
"external_ref" => "crm-8812"
], JSON_UNESCAPED_UNICODE),
]);
$doc = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) { throw new Exception($doc["error"]["code"]); }
echo $doc["number"], " ", $doc["view_url"];The 201 response carries the document number, the totals as computed, a view link and a PDF link:
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"public_id": "RFayPUSCNKnD",
"type": "quote",
"number": 1328,
"status": "open",
"date": "2026-09-07",
"due_date": null,
"external_ref": "crm-8812",
"customer": {
"id": "3f9c2a1e-6b7d-4c8e-9f0a-1b2c3d4e5f60",
"name": "ישראל ישראלי בע\"מ",
"tax_id": "515123456"
},
"totals": {
"subtotal": 2500,
"discount": 0,
"vat": 450,
"vat_rate": 18,
"total": 2950,
"paid": 0,
"currency": "ILS"
},
"allocation_number": null,
"allocation": {
"status": "not_required",
"number": null,
"reason": null
},
"delivery": {
"status": "disabled",
"channel": null,
"scheduled_for": null
},
"view_url": "https://doc.chat-invoice.co.il/view/RFayPUSCNKnD",
"pdf_url": "https://doc.chat-invoice.co.il/pdf/RFayPUSCNKnD",
"based_on": null,
"cancelled_at": null,
"created_at": "2026-09-07T10:21:44.120Z"
}
A paid tax invoice receipt for an existing customer (customer.id), with a total check:
{
"type": "tax_invoice_receipt",
"customer": {
"id": "3f9c2a1e-6b7d-4c8e-9f0a-1b2c3d4e5f60"
},
"items": [
{
"description": "שירות חודשי — ספטמבר",
"quantity": 1,
"unit_price": 590
}
],
"payments": [
{
"method": "bank_transfer",
"amount": 590,
"reference": "778812"
}
],
"expected_total": 590,
"external_ref": "order-10021"
}
02Authentication & security
- Every request carries
Authorization: Bearer ci_live_…. The key identifies the business; all documents and customers are scoped to it. - The key is a secret: never in client-side code, a mobile app or git. There is no CORS — the API is server-to-server.
- Revocation is immediate, from the same screen. Hold several keys (one per system) if you like.
Idempotency-Keyis required on every issue. It is what prevents a duplicate invoice when a request times out and you retry: same key + same body → the same document (withIdempotent-Replayed: true). Same key + different body →409.- Every response returns
X-Request-Id— quote it to support.
03What a business may issue
The legal type of the business decides which documents are lawful. An exempt dealer (osek patur), an NPO or a public institution does not issue tax invoices — it issues a receipt for a payment and a proforma invoice as a payment request. Such a request gets 422 legal_type_forbidden and no number is consumed. GET /v1/document-types returns only what this business may issue.
| type | Hebrew | English | payments | discount | exempt dealer / NPO |
|---|---|---|---|---|---|
quote | הצעת מחיר | Quote | not allowed | yes | yes |
order | הזמנה | Order | not allowed | yes | yes |
delivery_note | תעודת משלוח | Delivery note | not allowed | yes | yes |
return_note | החזרה מלקוח | Return note | not allowed | yes | yes |
proforma | חשבונית עסקה | Proforma invoice | not allowed | yes | yes |
tax_invoice | חשבונית מס | Tax invoice | not allowed | yes | no |
tax_invoice_receipt | חשבונית מס/קבלה | Tax invoice receipt | required | yes | no |
receipt | קבלה | Receipt | required | no | yes |
credit_note | חשבונית זיכוי | Credit note | not allowed | yes | no |
donation_receipt | קבלה על תרומה | Donation receipt | required | no | yes |
400.- Date (
date) — defaults to today. Never in the future and never earlier than the last document of the same type (the Israeli sequence rule). Error:422 date_before_last_documentwith the earliest allowed date. - Customer — either
customer.idof an existing customer (fromGET /v1/customers) orcustomer.name+ details. A name that already exists attaches to that card; new details only fill empty fields, never overwrite. A tax id that belongs to a differently-named customer →409 customer_identity_conflict, so a document is never attached to the wrong customer. - Source document (
based_on) — a receipt against a tax invoice closes it automatically; a credit note requires one.
04Amounts, VAT and payments
- Send items (
description,quantity,unit_price) and optionally a document discount. We compute subtotal, VAT and rounding — with the same engine as the chat and the app. prices_include_vatsays whether your unit prices are gross. Defaults to the business setting (see/v1/me). The VAT rate comes from the business settings (exempt dealers and Eilat businesses: 0).expected_totalis a safety net: if our total differs by more than 0.01 the document is not issued (422 total_mismatchwith our figure).- Payments are required on receipt / tax invoice receipt / donation receipt and not allowed elsewhere. They must sum to the total.
| method | עברית | extra fields |
|---|---|---|
cash | מזומן | — |
bank_transfer | העברה בנקאית | reference |
credit_card | כרטיס אשראי | card_last_digits, card_type |
check | המחאה | check_number, check_date, bank_code, branch, account |
bit · paybox · paypal · apple_pay · google_pay | ביט · פייבוקס · PayPal · Apple Pay · Google Pay | reference |
05Allocation number (חשבונית ישראל)
A tax invoice, tax invoice receipt or credit note above ₪5,000 net (before VAT) needs an allocation number from the Israel Tax Authority for the customer to reclaim VAT. When the business is connected (tax_authority_connected in /v1/me) we request the number automatically after issuing and bake it into the PDF.
- This needs the customer's tax id — send
customer.tax_id(or have it on the customer card). - The document is always issued. If the tax id is missing, the business is not connected, or the authority did not answer, the document goes out without an allocation number and
allocation.statussays exactly why:issued·not_required·skipped_customer_tax_id_missing·skipped_business_tax_id_missing·failed. - Later completion: the business owner asks in chat to complete the allocation for that document number.
06Delivery to the customer
If the business has auto-send enabled (Settings → Automation), every document issued through the API is sent to the customer on the configured channel — WhatsApp, email or both — exactly like a chat-issued document, including quiet hours (a document issued at night goes out in the morning). delivery.status reports: queued · deferred_quiet_hours (+scheduled_for) · no_recipient (no phone/email on the card) · disabled · suppressed · send_failed.
Prefer to send yourself? Pass "send": false and use view_url (hosted page) or pdf_url (file). The accountant copy follows the business settings regardless.
07Cancel & credit
An issued document is never deleted — its number stays in the book.
- Quote, order, delivery note, return note, proforma —
POST /v1/documents/{id}/cancelmarks it cancelled. - Tax invoice, tax invoice receipt, receipt — no cancel. Issue a credit note (
type: credit_note,based_on: the invoice id) with the same items. A cancel attempt returns422 use_credit_notewith a ready example.
{
"type": "credit_note",
"based_on": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"customer": {
"id": "3f9c2a1e-6b7d-4c8e-9f0a-1b2c3d4e5f60"
},
"items": [
{
"description": "זיכוי — שירות חודשי ספטמבר",
"quantity": 1,
"unit_price": 590
}
]
}
08Limits, subscription, versioning
- 60 requests per minute and 300 documents per day per key (
RateLimit-*headers;429withRetry-After). Need more? Talk to us. - The API is available to businesses with an active subscription. Otherwise you get
402 subscription_requiredwith a payment link indetails.payment_url. - A business that issues through external accounting software (iCount, Green Invoice, …) cannot use the API (
403). /v1is stable. New response fields are not breaking — ignore unknown fields. Breaking changes get/v2. Changelog.
09Errors
Every error has the same shape: a stable code, a message, a hint on what to do, and a retryable flag:
{
"error": {
"code": "legal_type_forbidden",
"message": "This business type may not issue the requested document type.",
"message_he": "סוג העוסק אינו רשאי להפיק מסמך מסוג זה.",
"hint": "GET /v1/document-types lists what this business may issue. An exempt dealer (osek patur) issues receipts / proforma invoices instead of tax invoices.",
"retryable": false,
"doc_url": "https://api.chat-invoice.co.il/docs/errors#legal_type_forbidden"
},
"request_id": "5f1c9b2e-0d4a-4b1e-9d1c-2f7a1b3c4d5e"
}
Full catalog: /docs/errors · as JSON: GET /v1/errors.