iCount exposes a v3 API with token authentication, but most of what determines the project is not the HTTP call. The v3 versus legacy trap, why old code samples will mislead you, and the decisions that actually cost time.
Key takeaways
- The iCount API is v3: a POST with JSON to api.icount.co.il/api/v3.php/ plus module and method, authenticated with a Bearer API token. Code found online that calls another URL was written for the older interface.
- Send a sanity_string with every doc/create. iCount refuses a second document with the same value, so a retried request becomes an error instead of a duplicate tax document.
- The API token is a full credential - it authorises issuing tax documents in the business's name. Server-side secrets only, and never in a browser.
- The expensive decisions are identical to every other invoicing integration: document type, VAT handling, retry safety and who issues the document. None of them are technical.
The iCount API is version 3: every call is a POST with a JSON body to https://api.icount.co.il/api/v3.php/ followed by a module and a method, such as doc/create, and the recommended authentication is an API token in an Authorization: Bearer header. Through it iCount, a cloud invoicing and business-management system, exposes documents, clients, payments and webhooks. This guide covers the calls that matter and the decisions that cost more than the code.
How do you authenticate to the iCount API?
iCount's own documentation, at apiv3.icount.co.il, lists three authentication methods and recommends the first one for every integration:
| Method | How it works | Expiry | Fits |
|---|---|---|---|
| API token (recommended) | Generated on the API tokens settings page, sent as Authorization: Bearer <token> | None - valid until revoked | Server-to-server integrations, background jobs, webhooks |
Session id (sid) | One call to auth/login with cid, user and pass; the returned sid goes into later request bodies | 20 minutes from the last request | Interactive tools making many calls in a short window |
| Credentials on every request | cid, user and pass in each request body | Not applicable | Quick scripts and testing |
Two details from that page shape the design. A token inherits exactly the permissions of the user it was created under, so the clean way to limit an integration is a dedicated iCount user with restricted rights and a token generated under that user. And a background job built on a sid starts failing after 20 idle minutes unless it logs in again - one more reason to use the token.
The old-code trap
Searching "iCount API" still returns code written for an older generation of the interface, some of it over a decade old. It looks plausible, it runs, and it fails. Because v3 itself still accepts a company id, username and password, a password in the body no longer tells you which generation you are looking at. The URL does: an example that does not call api.icount.co.il/api/v3.php/ was not written for v3. The iCount community node for n8n, for instance, asks for an API token, which is a good sign it targets the current interface.
The full method list is browsable at apiv3.icount.co.il, grouped into modules such as doc, client, webhook, paypage and reports. Take the exact request shape from there, against the version running now, and prepare the decisions further down in advance, because they are the real cost.
doc/create: the fields that matter
Creating a document is a POST to doc/create. The only field marked required is doctype, a string. The documentation lists invoice, receipt, invrec (invoice-receipt), refund, deal, offer, order, trec and delcert, and notes that the list varies by company type, so read yours from doc/types.
| Field | Purpose |
|---|---|
client_id, custom_client_id, vat_id, email, client_name | Who the document is for. iCount looks the client up in exactly this order, and creates a new client if none matches |
items | The document rows; optional only for a receipt, a donation receipt and a refund |
cash, cheques, banktransfer, cc, payments | The payment breakdown; a receipt or an invoice-receipt needs at least one |
sanity_string | A unique string of up to 30 characters; a second document with the same value is refused |
send_email | Whether iCount emails the original to the client (default false) |
A successful call returns docnum, doc_url, doc_copy_url and, when applicable, invoice_reference_number - the number issued by the Tax Authority. Store all of them. A failure comes back as JSON with "status": false and a machine-readable reason such as auth_required, bad_doctype or client_not_found; branch on reason and show error_description to a person.
The client rule deserves its own warning. If your system sends a vat_id with a typo and no client_id, the lookup finds nothing and iCount opens a second client for the same business. Send the iCount client_id you stored, or your own id in custom_client_id, on every call.
The decisions that actually cost time
Once the first call works, the differences between invoicing systems all but vanish. What remains is identical everywhere - and it is what sinks projects.
1. Which document, and when
Tax invoice, combined invoice-receipt, receipt and credit note are not interchangeable. The choice determines when revenue is recognised, which is an accounting question rather than a technical one.
This is the business accountant's decision. If your system decides on its own which document to issue and at what point in the process, that decision needs written sign-off. A developer choosing a document type by reasoning is a risk.
2. The retry problem
This catches almost every first invoicing integration, in every system.
You send a request, the server issues the document, and the connection drops before the response returns. Your code sees a timeout, reads it as failure, and retries - and now there are two tax documents with two sequential numbers. A tax document cannot be deleted; cancellation is an offsetting document, and someone has to handle it by hand.
Three rules:
- A timeout is not a failure - it is an absence of knowledge. Do not retry automatically.
- Store your own unique reference on the order, and before any retry check whether a matching document already exists.
- A missing document beats a duplicate. The first is fixed in a minute; the second needs a cancellation, a paper trail and a conversation with the bookkeeper.
In iCount the guard for this is sanity_string. Put your order reference in it (30 characters at most) and a retried doc/create for the same order is refused with doc_exists_based_on_sanity_string instead of producing a second tax document. Treat that error as "already issued", find the existing document with doc/search, and move on.
3. VAT and exempt dealers
Whether the amounts you send include VAT - verify against a real document rather than assuming. That is a five-minute check that prevents a month-long correction.
And an exempt dealer does not issue a tax invoice at all. If your system serves more than one dealer type, that changes the document type it issues.
4. Who issues the document
If a payment gateway is also in the picture and configured to issue a document automatically on payment, and your system also issues one, a single transaction produces two tax documents. This is the most common design mistake when payments and accounting touch the same project, and it surfaces at month end. Pick one side and document it before writing a line.
5. Allocation numbers
The Tax Authority requirement applies regardless of which system you chose. Confirm the flow handles it before go-live - see invoice allocation numbers for developers.
Does iCount support webhooks?
Yes, and they are managed through the API itself. webhook/add takes an action, a url and an optional method - GET, POST, JSON or XML, with JSON as the default - and returns a webhook_id. The actions you can subscribe to come from webhook/valid_actions, and webhook/get_list shows what is already registered. Check that the event you need is on that list before designing around it.
Where push does not cover an event, polling does: doc/search filters by start_date and end_date, doctype and status, and client/get_open_docs and client/get_balance answer the question a CRM asks most often - what this customer still owes.
Security
The iCount API token authorises issuing tax documents in the business's name. It does not expire on a fixed schedule. So:
- Environment variables or a secrets manager only
- Created under a dedicated user with only the permissions the integration needs, since the token inherits that user's rights
- Not in source control, not in logs, and not in any code running in a browser
- If a token leaks - rotate it in the interface, do not "monitor and see"
And persist the full API response even on success: the document id, its sequential number and its link. That is your only evidence when an accounting question arrives six months later.
A test environment
A tax document issued by mistake is not a row you delete - it exists for tax purposes. So ask iCount support explicitly whether a test environment exists and how to get access. It is an entirely fair question, and worth asking before committing to a client timeline rather than after.
In any case: keep the base URL and the token as two separate environment variables, so moving between environments is a configuration change rather than a code change.
Checklist
- Open the current official documentation and work from it - not from an example you found.
- Confirm you are on v3, judged by the URL:
api.icount.co.il/api/v3.php/. - Establish whether there is a test environment before starting.
- Get written confirmation from the accountant on which documents are issued and when.
- Verify VAT handling against a real document.
- Build duplicate protection before issuing the first production document, with a
sanity_stringon everydoc/create.
For a comparison of the Israeli systems, see the Israeli invoicing API comparison; for wiring iCount to a sales system, see connecting invoicing software to a CRM.
Sources
Frequently asked questions
Does iCount have an API?
Yes. iCount publishes a v3 API at https://api.icount.co.il/api/v3.php/ where every call is a POST with a JSON body to a module and method, such as doc/create. The recommended authentication is an API token in an Authorization: Bearer header, and the method reference is published at apiv3.icount.co.il.
Why does old iCount example code stop working?
Because it was written for an older generation of the interface that calls a different URL. The current interface is v3 at api.icount.co.il/api/v3.php/, with an API token as the recommended authentication. v3 still accepts a company id, username and password, so check the URL, not the password, to tell which generation an example targets.
What is the most common bug in an invoicing API integration?
Retrying after a timeout. A timed-out request may well have succeeded on the server, so an automatic retry produces two tax documents with two sequential numbers - and a tax document cannot be deleted, only offset with a counter-document. Store a unique reference on your order and check whether a document already exists before any retry.
Who decides which document type the system issues?
The business's accountant, not the developer. The choice between a tax invoice, a combined invoice-receipt and a receipt determines when revenue is recognised, which is an accounting decision with real consequences. Get it in writing before building logic that selects a document type automatically.
How should an iCount API token be stored?
As a server-side secret in an environment variable or secrets manager. It authorises issuing tax documents in the business's name and does not expire on a fixed schedule, so it must never appear in source control, logs, or anything running in a browser. If it leaks, rotate it in the interface immediately rather than monitoring for misuse.
Does the iCount API token expire?
No. According to iCount's documentation an API token has no expiration and works until you revoke it, and it carries exactly the permissions of the user it was created under. A session id from auth/login is different: it stays valid for 20 minutes from the last request and then needs a new login.
How do you stop the iCount API from issuing a duplicate document?
Send a sanity_string with doc/create - a unique value of up to 30 characters, such as your order reference. If a document with the same value already exists, iCount refuses the request with doc_exists_based_on_sanity_string, so a retry after a timeout cannot produce a second tax document.
Why does the iCount API create duplicate clients?
Because doc/create looks the client up by client_id, then custom_client_id, vat_id, email and client_name, and creates a new client when nothing matches. A tax id with a typo or a changed email is enough to open a second record. Store iCount's client_id, or send your own id in custom_client_id, on every call.
Keep reading
Related service
Integrations
Make the systems you already pay for talk to each other.
Have a project like this?
Tell me what you're trying to automate or build. I reply within 24 business hours with a few targeted questions, then we walk through it on a free 30-minute call, with no commitment. You come away with a scope, a timeline and a fixed price - or a straight answer that it isn't worth building.