Four single-file clients with the same surface. No package manager, no dependencies: copy the file into your project. They live in the repository under integrations/sdk/.
| Language | File | Requires | Style |
|---|---|---|---|
| Node.js | node/slk-invoices.mjs (+ slk-invoices.d.ts) | Node 18+ | ESM, built-in fetch, JSDoc types |
| PHP | php/SlkInvoices.php | PHP 7.4+, cURL | class SlkInvoices, arrays in/out |
| Python | python/slk_invoices.py | Python 3.8+ | urllib, snake_case |
| C# | csharp/SlkInvoices.cs | .NET 6+ | HttpClient, System.Text.Json, async |
Each folder has a README with install-by-copy and a ten-line example.
Surface#
| Operation | Node | PHP | Python | C# | Endpoint |
|---|---|---|---|---|---|
| Issue (native shape) | createDocument(id, doc) | createDocument($id, $doc) | create_document(id, doc) | CreateDocumentAsync(id, doc) | POST /create-document |
| Issue (Invoice4U shape) | createDocumentCompat(doc) | createDocumentCompat($doc) | create_document_compat(doc) | CreateDocumentCompatAsync(doc) | POST /create-document |
| Search documents | listDocuments(filters) | listDocuments($filters) | list_documents(**filters) | ListDocumentsAsync(...) | GET /documents |
| One document | getDocument(id) | getDocument($id) | get_document(id) | GetDocumentAsync(id) | GET /documents?id= |
| Customers | listCustomers(q), createCustomer(c) | same | list_customers, create_customer | ListCustomersAsync, CreateCustomerAsync | GET/POST /customers |
| Totals | calculate(doc) | calculate($doc) | calculate(doc) | CalculateAsync(doc) | POST /calculate |
| Verify a webhook | verifyWebhook(raw, sig, secret) | SlkInvoices::verifyWebhook(...) | verify_webhook(...) | SlkInvoicesClient.VerifyWebhook(...) | offline |
Behaviour#
- The base URL defaults to
https://invoice.slk.co.il. Pass an origin, or thebaseUrla sandbox signup returns (…/api/billing/v1); both work. - The key is sent as
X-Api-Key.createDocumentCompatsends it astokenin the body instead, as the Invoice4U shape requires, and you pass just thedocobject. - Every non-2xx answer raises an error carrying the HTTP
status, the server'smessage(fromerrorord.ErrorMessage) and the parsedbody:SlkInvoicesError(Node, Python),SlkInvoicesException(PHP, C#). create-documentis idempotent: re-calling with the same identifier returns the same document, so wrapping it in your own retry loop is safe. The SDKs do not retry by themselves.- Timeouts default to 30 seconds.
- Money is integer agorot, quantities ×1000, VAT in basis points — the SDKs pass your data through untouched. See overview.
- Python's
list_documentstakesfrom_for thefromfilter, becausefromis a keyword.
verifyWebhook#
verifyWebhook(rawBody, signatureHeader, secret[, toleranceSeconds]) checks X-SLK-Signature (t=<unix>,v1=<hex>): HMAC-SHA256 of "<t>.<rawBody>" compared in constant time. It also rejects a timestamp more than 300 seconds off (pass 0 to skip that check, e.g. when replaying stored events). Always pass the raw body, before JSON parsing. See webhooks.
Testing#
The Node SDK and the signature algorithm are covered by test/sdk.test.ts, which also cross-checks the Python implementation against the server's own signer. The PHP and C# clients follow the same algorithm but are not exercised by the repository's test run; if you find a discrepancy, treat the OpenAPI document as the source of truth.
For other languages, generate a client from GET /api/billing/v1/openapi.json.