Get started
The ChatFood API lets your systems do what you do in the web app: read the performance of your pages, list them, schedule broadcasts, register conversion pixels and more. Every route is under /v1 (for example GET /v1/pages) and every call is authenticated with an API token that you create in the web app and that can only do what you allow.
1. Create a token
- Log in to the web app and open Configurações > Tokens de API.
- Choose a name that says who will use it (for example, "ERP reports").
- Pick the account the token may act on. A token bound to one account never sees the others.
- Pick the scopes: the least the task needs.
metrics:readis enough for reports; sending broadcasts needsbroadcasts:writeandflows:read. - Set an expiry whenever the use is temporary.
- Copy the token (
cf_live_...). It is shown only once: ChatFood keeps just a hash of it.
Treat the token like a password. Keep it in a secret store on your server, never in the browser, in a URL or in a repository.
2. How tokens and scopes work
An API token is a long-lived credential bound to a user, to a set of scopes and, optionally, to ONE of that user's accounts. Format: cf_live_ followed by 43 URL-safe base64 characters (regex cf_live_[A-Za-z0-9_-]{43}, so secret scanners can find a leaked one). Send it in either header:
Authorization: Bearer cf_live_...
X-Api-Key: cf_live_...
Scopes follow area:access, where access is read or write and write implies read:
| Scope area | What it covers |
|---|---|
pages |
pages (/v1/pages), connection history (/v1/connections), Meta and Telegram page connection, ice breakers, page variables, alerts |
leads |
leads (/v1/leads), lead tags (/v1/tags), deleting the leads of a page |
flows |
flows (/v1/schemas), utility templates, Meta message templates, media upload (/v1/uploads, /v1/voice-messages), POST /v1/schemas/{schemaId}/test |
broadcasts |
/v1/broadcasts and its executions |
journeys |
/v1/journeys |
metrics |
/v1/alerts/summary, /v1/schemas/{schemaId}/metrics*, /v1/pages/{pageId}/send-time-suggestion and the GraphQL endpoint; broadcastCalendar* also needs broadcasts:read and profileCalendar also needs leads:read (without them the result is empty) |
websites |
/v1/website-domains and /v1/websites |
pixels |
/v1/meta/datasets |
payments |
reserved for Pix reports (not published yet) |
account |
account settings, UTM and language slugs, Meta apps, notifications, categories and variable groups |
users |
listing account members (GET /v1/accounts/{accountId}/users). Adding and removing members is not available to API tokens |
billing |
/v1/billing/* |
Rules:
GETneedsread; other verbs needwrite. Exceptions are declared by the route:POST /v1/schemas/validate-variablesneedsflows:read;POST /v1/website-domains/validate-scriptneedswebsites:read;POST /v1/broadcasts/delivery-previewneedsbroadcasts:readandPOST /v1/journeys/delivery-previewneedsjourneys:read.- A route that declares no area is not available to API tokens. So are admin routes, internal routes, token management and account or member lifecycle. The response is
403with aproblem+jsondetail naming what is missing. - A token never exceeds its owner. In each account, a request can do only what both the token scopes and the owner's permissions in that account allow. If the owner loses an account or a permission, the token loses it on the next request.
- It acts as the owning user but NEVER carries administrative roles. A token created by a SUPER_ADMIN cannot reach
/admin/*routes and cannot cross account boundaries. - If
accountIdwas set at creation, the principal sees only that account:GET /v1/accountsreturns just it,?accountId=must match it, and resources of other accounts answer403/404. - Only the SHA-256 hash is stored. The plaintext appears once, in the creation response.
- It can expire (
expiresAt) and can be revoked at any time. Revoked or expired tokens get401immediately.lastUsedAtandlastUsedIpare updated at most once per minute. - Requests are rate limited per token (default 120 per minute per API instance). Over the limit, the answer is
429withRetry-After. - Every write made with a token is recorded in the audit log with the token id.
Endpoints. All require a user session (JWT) except GET /v1/me. An impersonation session cannot create tokens (403):
| Method | Path | Body | Response |
|---|---|---|---|
| POST | /v1/api-tokens |
{"name": "string (1-100)", "scopes": ["broadcasts:write", "metrics:read"], "accountId": "guid? (one of the user's active accounts, otherwise 400)", "expiresAt": "ISO date? (future)"} |
201 {"id", "name", "prefix", "accountId", "scopes", "expiresAt", "createdAt", "isActive", "token": "cf_live_..."}. token is returned ONLY here. 400 for an unknown scope (invalid lists them) or for scopes above the user's own permissions |
| GET | /v1/api-tokens |
none | {"items": [{"id", "name", "prefix", "accountId", "scopes", "expiresAt", "lastUsedAt", "lastUsedIp", "revokedAt", "createdAt", "isActive"}], "nextCursor"} (never the hash or the secret) |
| GET | /v1/me |
none | {"authenticationMethod": "api_token"|"jwt", "user": {"id", "name", "email"}, "accounts": [{"id", "name", "status", "permissions": ["area:access"]}], "token": {...}|null}. Use it to discover what the credential you hold can do in each account. status is 1 (active) or 0 (blocked): a blocked account takes no writes and stays out of the reads without accountId |
| DELETE | /v1/api-tokens/{tokenId} |
none | 204; 404 when the token is not the caller's |
Recommended bootstrap for an agent: a human logs in once (POST /Auth) and creates a token with the least scopes the task needs, for the right account and with an expiry. The human hands the cf_live_ value to the agent. The agent then calls GET /v1/me to confirm the account and permissions, and never needs the password.
3. Your first call
curl -s "$API/v1/me" -H "Authorization: Bearer $CF"
Read accounts[].id and accounts[].permissions. If the account you need is absent, or lacks the permission, stop and ask the owner for another token: retrying will not help.
4. Try it on this site
Open the API reference, click Authentication, paste your token in the Bearer field and use Test request on any route. The token stays in your browser tab: this site does not store it, and the request goes straight from your browser to the API.
Every route in the reference shows the scope it needs (x-required-scope) and ready-made examples in curl, JavaScript and Python.
5. Collections and the OpenAPI document
- Postman collection: import it in Postman or Bruno, then fill the
tokenvariable. - OpenAPI document: only the
/v1routes an API token can call, generated from the code with the same rule the server enforces. Any OpenAPI tool (Bruno, Insomnia, code generators) can import it.