Looker Studio or Power BI
A dashboard that combines your ZeroChats leads with your ad spend and works out the real cost per client.
The ZeroChats API lets you work with your business data from outside the platform. You generate a key, drop it into the tool you already use, and that tool talks to ZeroChats directly. Today it covers two things:
It answers a very concrete problem: your ZeroChats data lives in ZeroChats and the rest — ad spend, bookings, payments, invoicing — lives somewhere else. With the API you put them together without exporting a CSV every Monday, and when something happens in another tool you can reflect it on the lead without opening the dashboard.
Looker Studio or Power BI
A dashboard that combines your ZeroChats leads with your ad spend and works out the real cost per client.
Google Sheets
A sheet that updates itself with this month’s leads and the conversions per sales link.
n8n, Make or Zapier
A flow that posts the week’s summary to Slack every Monday, and another that tags a lead and moves them to a new stage when someone books or pays in another tool.
Your own backend
Any service that can make an HTTP request with one header can consume it.
The API creates no leads and sends no messages. It can change a lead’s stage, tags and contact details through the leads endpoints; everything else stays read-only.
Go to Business setup and open the Integrations tab. The tools are listed under CRM, webhooks and tracking, one card per integration.
Find the ZeroChats API tile and click Create key.
Click Generate key. The key appears on screen, starts with zcst_ and is unique to your business.
Copy it right there. That’s the only time it is shown in full. After that you only see a shortened version, something like zcst_ab12…7yz9 — enough to recognise it, not enough to use it.
Store it in your tool and make a first call to check it answers.
Once created, the tile tells you whether the key has ever been used and when the last call was. That’s the quick way to confirm the integration on the other side is actually wired up: if it says no calls yet, your tool never managed to connect.
From that same dialog you can Regenerate the key (creates a new one and invalidates the previous one instantly) or Revoke it (deletes it; from then on every call gets an authorization error).
Read this whole section before pasting the key anywhere.
404, exactly like one that doesn’t exist.The base URL is:
https://app.zerochats.com/api/v1The key travels in the Authorization header:
curl -H "Authorization: Bearer zcst_your_key" \ https://app.zerochats.com/api/v1/meAdd an HTTP Request node:
GET, URL https://app.zerochats.com/api/v1/me.Authorization, value Bearer zcst_your_key.Save the credential once and reuse it in every node that calls the API.
const response = await fetch('https://app.zerochats.com/api/v1/me', { headers: { Authorization: `Bearer ${process.env.ZEROCHATS_API_KEY}` },});
const { success, data, meta } = await response.json();If your tool won’t let you set the Authorization header, we also accept the key in x-api-key with the same value, without the Bearer prefix.
GET /me returns no metrics and no leads: it just tells you which business the key belongs to and which time zone the statistics days are expressed in. It’s the cheapest way to check the key works before building anything on top of it.
{ "success": true, "data": { "id": "b7a2f1d9-5c34-4a61-8e2f-0d9c1b4a7e33", "name": "My business", "locale": "en" }, "meta": { "timezone": "Europe/Madrid" }}Every response has the same shape. When the call succeeds:
{ "success": true, "data": {}, "meta": {}}data changes per endpoint. meta only travels on the endpoints that have something to tell you: always on the statistics ones, with the period and time zone that produced the numbers; on /me, with the time zone; on the lead endpoints it is absent.
When something fails:
{ "success": false, "error": { "code": "invalid_request", "message": "provide exactly one of username, email or phone" }}Branch on error.code, which is stable. The message is written for you to read while you build the integration and may be reworded.
You can make 60 requests per minute, counting every endpoint together. That’s plenty for a dashboard refreshing hourly, a daily report or a flow that updates leads as bookings come in; you’ll only hit it if you build a loop that walks many days or many leads one at a time.
Every response tells you where you stand:
| Header | What it is |
|---|---|
X-RateLimit-Limit | Requests allowed per minute. |
X-RateLimit-Remaining | How many you have left this minute. |
X-RateLimit-Reset | When the budget renews, in Unix seconds. |
Retry-After | Seconds you must wait. Only when you go over. |
When you go over you get a 429 with error.code set to rate_limited. The right way to handle it is to wait the number of seconds in Retry-After and retry: by the time you come back you’ll have the full budget. Retrying sooner only burns attempts.
| HTTP status | error.code | What happened |
|---|---|---|
| 401 | unauthorized | The header is missing, or the key is mistyped, revoked or no longer exists. |
| 400 | invalid_request | A parameter or the body is invalid. The message tells you which. |
| 404 | not_found | The lead doesn’t exist or doesn’t belong to your business. |
| 429 | rate_limited | You went over 60 requests in the current minute. |
| 500 | internal_error | Something failed on our side. Retry with a wait and, if it persists, open a ticket. |
A 401 after everything had been working usually means one of two things: someone regenerated the key from the app, or revoked it. Open the dialog and check the creation date.
id as your key, not name. Tag, content and sales-link names can be changed from the app; identifiers can’t. The same goes for leads: the id the webhook or the lookup gives you is stable, the username can change.