Endpoint
Tutti gli endpoint REST sotto l'indirizzo base. Ogni voce mostra il permesso necessario, i campi e le risposte.
Il riferimento tecnico qui sotto è in inglese, esattamente come nomi e campi appaiono nell'API e in Claude.
59 endpoints · Base URL https://api.smartchat.marketing/v1 · OpenAPI: openapi.json
Account
GET/v1/me
Get the authenticated account and key (test connection)
No scope needed; any valid key works. Use it to test a connection.
account.name is a good connection label. key is null when called
through OAuth/MCP.
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Contacts
GET/v1/contacts
List contacts
Requires scope contacts:read. Non-deleted contacts of the account,
newest first (created_at descending, then id). With q: partial match in
name, email or phone number, case-insensitive. A phone search may contain
spaces and hyphens ("+49 151 123" finds "+49151123...").
contacts:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
q | query | no | string · Search term (name, email or phone, partial match). Empty means no filter. max length 100 |
limit | query | no | integer · min 1 · max 200 · default 50 |
offset | query | no | integer · min 0 · max 100000 · default 0 |
created_after | query | no | string · Only contacts created strictly after this time. format date-time |
Risposte
200 | OK |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/contacts
Create (or upsert) a contact
Requires scope contacts:write. At least email or phone is required.
New contacts start with optin_whatsapp=none / optin_email=none; a
double opt-in cannot be triggered through this API. The contact must go
through the regular sign-up flow before /messages can reach it.
Upsert (body upsert: true or query upsert=true): if a contact with the
same email or phone exists, it is updated (name/email/phone) and 200 is
returned with created: false. Changing an email or phone resets the
opt-in for that channel to none; the opt-in can never be raised via the
API. Without upsert, a duplicate returns 409 contact_exists (key
kontakt_email_doppelt, kontakt_nummer_doppelt or kontakt_doppelt,
plus contact_id). If the email matches one contact and the phone
another, 409 contact_conflict is returned with contact_ids.
403 limit_reached when the plan's contact limit is reached.
contacts:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
upsert | query | no | boolean · default false |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 120 |
email | string | no | format email |
phone | string | no | International format, e.g. +49170... |
acquisition | string ("marketing", "automation", "service") | no | default "marketing" |
upsert | boolean | no | default false |
{
"name": "Max Sample",
"phone": "+491701234567",
"acquisition": "marketing"
}Risposte
200 | Existing contact updated (upsert) |
201 | Created |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
409 | Contact already exists (contact_exists), matches two contacts (contact_conflict), or idempotency request in progress. |
422 | Idempotency key reused with a different request body or path (idempotency_key_mismatch) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/contacts/tags
All assigned tags with counts
Requires scope contacts:read. If the same name comes from several
origins, the stronger origin wins for display (system > ki > manuell).
capped = true means the limit of 1000 checked contacts was reached and
the count is incomplete.
contacts:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/contacts/{id}
Get a contact
Requires scope contacts:read.
contacts:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/contacts/{id}
Update a contact
Requires scope contacts:write. Only the given fields are changed.
IMPORTANT: if email or phone changes, the opt-in for EXACTLY THAT
channel falls back to none. Consent cannot be moved to another address
or number; through this route an opt-in can only fall, never rise.
The contact must still have at least an email or a phone number. A
duplicate email or phone returns 409 contact_exists.
contacts:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 120 |
email | string | no | format email |
phone | string | no | International format, e.g. +49170... |
{
"name": "Maxi Sample",
"phone": "+491709999999"
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
409 | Another contact already has this email or phone (contact_exists). |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/contacts/{id}
Permanently delete a contact
Requires scope contacts:delete; contacts:write is NOT enough.
Deletes the same scope as the SmartChat app: pending send jobs,
conversations and messages, personal automation runs, then the contact
itself. Events and consent records are ANONYMIZED instead of deleted (the
statistics stay consistent, and the proof THAT consent existed remains).
If the end customer requested deletion, a deletion confirmation is sent
to them afterwards (Art. 19 GDPR).
contacts:delete| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Deleted |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/contacts/{id}/tags
Add tags
Requires scope contacts:write. Either tag (single) or tags (list).
Added tags have the origin manuell (manual).
System tags (e.g. "hat gekauft", "marketing", "herkunft: ...") are
rejected with 400: they describe what actually happened and must not be
claimed by hand. At most 30 tags per contact.
contacts:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
tag | string | no | max length 40 |
tags | array of string | no |
{
"tags": [
"regular",
"newsletter"
]
}Risposte
200 | OK |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/contacts/{id}/tags/{tag}
Remove one tag
Requires scope contacts:write. System tags cannot be removed (400);
they are a record, not a label.
contacts:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
tag | path | sì | string · URL-encoded tag name. |
Risposte
200 | OK |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Inbox
GET/v1/inbox/conversations
List inbox conversations
Requires scope inbox:read. Newest first. automated_only marks
conversations that consist only of automated campaign messages
(broadcast/follow-up/automation/opt-in), i.e. without a real customer
reaction.
There is deliberately NO reply endpoint. To write from an integration,
use POST /messages, where the opt-in requirement is visible and checked.
inbox:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
channel | query | no | string ("whatsapp", "email") · |
limit | query | no | integer · min 1 · max 100 · default 25 |
offset | query | no | integer · min 0 · default 0 |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/inbox/conversations/{id}/messages
Read the history of a conversation
Requires scope inbox:read. Returns the NEWEST limit messages (default
25, max 100), oldest first within the page. offset pages backwards from
the newest end. automated marks automated campaign messages, ai a
reply written by the SmartChat AI.
inbox:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
limit | query | no | integer · min 1 · max 100 · default 25 |
offset | query | no | integer · min 0 · default 0 |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Messages
GET/v1/messages
List messages account-wide (polling trigger "new inbound message")
Requires scope inbox:read. Newest first, stable sort (created_at
descending, then id).
inbox:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
direction | query | no | string ("inbound", "outbound", "in", "out") · "in"/"out" are accepted as aliases of inbound/outbound. default "inbound" |
limit | query | no | integer · min 1 · max 100 · default 25 |
offset | query | no | integer · min 0 · max 100000 · default 0 |
created_after | query | no | string · Only messages created strictly after this time. format date-time |
conversation_id | query | no | string · format uuid |
Risposte
200 | OK |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/messages
Send a WhatsApp free-text message or an approved template to a confirmed contact
Requires scope messages:write. The contact must already have
optin_whatsapp=confirmed (double opt-in); this route neither creates nor
bypasses an opt-in. Send EITHER text OR template, never both.
**Free text (text)** is sent immediately (201). WhatsApp rejects free
text outside the 24-hour service window (the send then fails with
send_failed).
**Template (template)** works at any time, also outside the 24-hour
window. Only the account's own WhatsApp templates with Meta status
approved can be sent (GET /templates shows sendable and
variables); opt-in confirmation and system templates cannot. Template
variables are filled from the contact (name = first name with a
language-specific fallback, full_name, email, phone, custom fields)
and from template.variables. name, full_name, email, phone and
a positional {{1}} used as greeting always come from the contact and
cannot be passed. Every other template variable must have a value; unknown
variables, empty values, values over 1024 characters, values with line
breaks, tabs, control characters or four spaces in a row, and values that
contain a placeholder are rejected with 422 invalid_variables (the
message names the variables). If the final text would still contain a
placeholder, nothing is sent.
A template message is checked immediately (contact, opt-in, opt-out list,
template status, variables, account lock, monthly quota, connected
number) and then QUEUED (202 with send_id). SmartChat sends it within
seconds through exactly the same path as every other message of the app
(opt-out and opt-in are checked again right before sending, monthly quota
is reserved atomically). Follow the result with GET /sends/{id}. Messages
cost no credits; each sent message counts against the monthly message
quota like any other message.
Links in the text: http(s) addresses get UTM parameters
(utm_source=smartchat, utm_medium=whatsapp, utm_campaign=api) and are
sent as a short link <app-host>/public/t/c/<id> so clicks are counted.
The short link redirects immediately. Unchanged are SmartChat's own
addresses, addresses with their own utm_source, signed addresses
(signature, token or expiry parameters also get no UTM) and texts that
would become too long.
messages:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
contact_id | string | sì | format uuid |
text | string | no | Free text. Not together with template. max length 4000 |
template | object | no | Approved template to send. Not together with text. |
template.id | string | sì | Template id from GET /templates. format uuid |
template.variables | object | no | Values for template variables that do not come from the contact. |
{
"contact_id": "3f2c8a1e-0000-4000-8000-000000000000",
"text": "...",
"template": {
"id": "3f2c8a1e-0000-4000-8000-000000000000"
}
}Risposte
201 | Free text sent |
202 | Template message queued |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | Missing scope, account blocked, sending paused (subscription_locked) or monthly quota used up (limit_reached). |
404 | Not found (or belongs to another account) |
409 | Contact not opted in (contact_not_optin), contact opted out (contact_opted_out), no phone number, no WhatsApp number connected (wa_not_connected), or idempotency request in progress. |
422 | Template not approved (template_not_approved), not a WhatsApp template (template_not_whatsapp), template type not sendable (template_not_sendable), invalid or missing variables (invalid_variables), or idempotency key reused with a different request (idempotency_key_mismatch). |
429 | Too many requests for this key (120 per minute), code rate_limited |
502 | Sending via the provider (WhatsApp) failed (send_failed). |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/sends/{id}
Status of a queued template message
Requires scope messages:write. Only template sends created with
POST /messages (template) of this account; everything else is 404.
messages:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Automations
GET/v1/automations
List automations
Requires scope automations:read.
automations:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/automations
Create an automation
Requires scope automations:write.
The same deterministic safety rules apply as in the SmartChat app: an
automation with a mailing-list/newsletter intent always gets a double
opt-in step prepended, and a follow-up sequence disguised as an
automation (several messages >= 24 h apart) is reduced to the first,
immediate message. So this route never creates an automation that sends
marketing to contacts without consent.
Triggers with a webhook (generic_webhook, purchase) automatically get
an address; it is available at GET /webhooks/{id} (scope webhooks:read).
Trigger type values are fixed identifiers: datum = date, termin =
appointment, inaktivitaet = inactivity.
automations:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | sì | max length 120 |
trigger_type | string ("purchase", "signup", "keyword", "datum", "termin", "inaktivitaet", "generic_webhook") | sì | Stable identifiers: datum = date, termin = appointment, inaktivitaet = inactivity. |
trigger_config | object | no | |
actions | array of object | sì | |
actions[].type | string ("message", "tag", "sequence", "webhook") | no | |
actions[].text | string | no | Only for type=message. |
actions[].channel | string ("whatsapp") | no | |
actions[].delay_minutes | integer | no | min 0 |
actions[].tag | string | no | Only for type=tag. |
actions[].sequence_id | string | no | Only for type=sequence. format uuid |
actions[].url | string | no | Only for type=webhook. |
actions[].condition | object | no | If/then condition on a field of the event. |
actions[].condition.field | string | no | |
actions[].condition.op | string ("eq", "contains", "gt") | no | |
actions[].condition.value | any | no | |
source | string ("generic", "manual", "shopify") | no | default "generic" |
contact_fields | array of string | no | Fields the form/tool sends. Always contains email OR phone. |
status | string ("active", "paused", "draft") | no | default "active" |
{
"name": "New order",
"trigger_type": "generic_webhook",
"actions": [
{
"type": "tag",
"tag": "customer"
}
]
}Risposte
201 | Created |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/automations/{id}
Get an automation
Requires scope automations:read. The secret hook token is NOT part of
the response; only has_hook says whether there is an address. The
address itself is available at GET /webhooks/{id}.
automations:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/automations/{id}
Update an automation (including activate/pause)
Requires scope automations:write. status: "active" activates,
"paused"/"draft" pauses.
Two behaviors to know: trigger_config is MERGED, not replaced (a
partial update does not silently remove the calendar address). And when
pausing, already queued pending messages of this automation are stopped;
otherwise a delayed action would still go out despite the pause.
automations:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 120 |
status | string ("active", "paused", "draft") | no | |
trigger_type | string ("purchase", "signup", "keyword", "datum", "termin", "inaktivitaet", "generic_webhook") | no | Stable identifiers: datum = date, termin = appointment, inaktivitaet = inactivity. |
trigger_config | object | no | |
actions | array of object | no | |
actions[].type | string ("message", "tag", "sequence", "webhook") | no | |
actions[].text | string | no | Only for type=message. |
actions[].channel | string ("whatsapp") | no | |
actions[].delay_minutes | integer | no | min 0 |
actions[].tag | string | no | Only for type=tag. |
actions[].sequence_id | string | no | Only for type=sequence. format uuid |
actions[].url | string | no | Only for type=webhook. |
actions[].condition | object | no | If/then condition on a field of the event. |
actions[].condition.field | string | no | |
actions[].condition.op | string ("eq", "contains", "gt") | no | |
actions[].condition.value | any | no |
{
"status": "active"
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/automations/{id}
Delete an automation
Requires scope automations:delete; automations:write is NOT enough.
Pending messages of this automation are stopped first, so nothing goes
out in its name after deletion.
automations:delete| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Deleted |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/automations/{id}/runs
Runs of an automation
Requires scope automations:read. Newest first.
automations:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
limit | query | no | integer · min 1 · max 200 · default 50 |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/automations/{id}/trigger
Trigger an automation with a payload
Requires scope automations:write. Runs the same action chain as a
regular trigger (webhook/internal event). There is no test mode; results
are real (messages are sent, etc.).
automations:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
payload | object | no | Free-form event object passed to the automation. |
{
"payload": {}
}Risposte
201 | Run started |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
409 | The current state does not allow the action (e.g. webhook_limit_reached, idempotency_in_progress) |
422 | Idempotency key reused with a different request body or path (idempotency_key_mismatch) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Webhooks
GET/v1/webhooks
List incoming webhook addresses of automations
Requires scope webhooks:read.
An incoming webhook is the inbound address of an automation with a
webhook trigger. There is no separate resource: CREATE means
POST /automations with trigger_type: generic_webhook (or purchase),
DELETE means deleting the automation. For outgoing event notifications
see /webhook-subscriptions.
Separate scope because the address contains the SECRET hook token: whoever
has it can trigger the automation without any API key, even after the key
was revoked. Rotating the token is deliberately not offered here.
webhooks:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/webhooks/{id}
Setup package of an incoming webhook (address, embed code, state)
Requires scope webhooks:read. {id} is the automation id. If the
trigger needs no address at all (e.g. keyword, datum), the API
answers 400.connection.state answers the question where most setups fail:
waiting_for_first_event (address ready, nothing received yet),
running (at least one real event received), not_connected (calendar
without address), internal (trigger needs no connection).
webhooks:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Webhook subscriptions
GET/v1/webhook-subscriptions
List webhook subscriptions
Requires scope webhooks:read.
webhooks:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/webhook-subscriptions
Subscribe a URL to an event (REST hook)
Requires scope webhooks:write plus the read scope of the event:
contact.created needs contacts:read; message.received and
conversation.created need inbox:read. Only available with an API key
(not via OAuth/MCP).
The URL must use https, be at most 2000 characters and resolve to a
public IP address. At most 10 active subscriptions per account (409
webhook_limit_reached). The signing secret (whsec_...) is returned
ONLY in this response. See the tag description for delivery details.
webhooks:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
url | string | sì | format uri · max length 2000 |
event | string ("contact.created", "message.received", "conversation.created") | sì |
{
"url": "https://hooks.example.com/smartchat",
"event": "message.received"
}Risposte
201 | Created |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
409 | The current state does not allow the action (e.g. webhook_limit_reached, idempotency_in_progress) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/webhook-subscriptions/{id}
Delete a webhook subscription
Requires scope webhooks:write. 404 if not found in this account.
webhooks:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Deleted |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Templates
GET/v1/templates
List templates
Requires scope templates:read. Each item also has variables (the
placeholders of the approved version, in order), settable_variables
(the ones that may be passed in POST /messages template.variables;
the rest comes from the contact), sendable (can be sent with
POST /messages right now) and language.
templates:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/templates
Create a template
Requires scope templates:write. The template is created as a DRAFT; it
is only submitted deliberately via POST /templates/{id}/submit (separate
scope templates:submit), so an unchecked template never burns a scarce
Meta submission slot.purpose controls the Meta category: optin_confirm and utility are
sent as UTILITY, marketing as MARKETING. Opt-in templates ALWAYS get
the fixed, language-bound confirm button; a custom button label would
break the YES detection in the webhook and thus the double opt-in, and is
rejected.language matters more than it seems: at Meta a template is identified by
(name, language). If omitted, the account language applies.
Check messages (issues, rejection_reason_text) are English.
templates:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | sì | max length 120 |
content | string | sì | max length 20000 |
channel | string ("whatsapp", "email") | no | default "whatsapp" |
subject | string | no | Only for channel=email. |
purpose | string ("marketing", "utility", "optin_confirm") | no | default "marketing" |
language | string | no | Meta language code, e.g. de, en_US. |
buttons | array of object | no | |
buttons[].type | string ("QUICK_REPLY", "URL") | no | |
buttons[].text | string | no | max length 25 |
buttons[].url | string | no | Only for type=URL. |
{
"name": "Welcome",
"content": "Hi {{1}}, great to have you here!",
"purpose": "marketing",
"language": "en_US"
}Risposte
201 | Created (draft) |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/templates/{id}
Get a template
Requires scope templates:read. state is the state
(draft/pending/approved/rejected/paused/disabled), submittable says
whether submitting makes sense right now, issues lists the reasons if not.
templates:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/templates/{id}
Update a template
Requires scope templates:write.
ANY content change to a WhatsApp template (text, button, language, name,
header image) resets meta_status to null. This is the WABA rule: the
changed version must not be sent under the old approval. After a change
the template must be submitted again.
templates:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 120 |
content | string | no | max length 20000 |
subject | string | no | |
language | string | no | |
buttons | array of object | no | |
buttons[].type | string ("QUICK_REPLY", "URL") | no | |
buttons[].text | string | no | max length 25 |
buttons[].url | string | no | Only for type=URL. |
header_media | object | no | Header image of the template; null removes it. |
{
"name": "...",
"content": "...",
"subject": "...",
"language": "...",
"buttons": [
{}
],
"header_media": {}
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/templates/{id}
Delete a template
Requires scope templates:delete. If the template is still attached to a
follow-up step or an automation, the API answers 409 instead of letting a
later send fail. A template known to Meta is also removed there; if that
fails, the reason is in notice - locally it is deleted anyway.
templates:delete| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Deleted |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
409 | Template is still attached to a follow-up step or an automation. |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/templates/{id}/submit
Submit a template to Meta
Requires scope templates:submit; templates:write is NOT enough.
Separate scope because something goes OUTSIDE here: Meta strictly caps
submissions per WABA, and rejected templates affect the quality rating of
the number.
The same deterministic check as in the SmartChat app runs first; if the
template fails, it is NOT submitted at all (400 with the reasons).
Without a connected WhatsApp number: also 400.
If the template is already at Meta (approved/pending), 200 is
returned with already: true and a plain-text notice instead of a false
error. If the submission did not reach Meta, the answer is 502 with the
reason, never a sugar-coated ok.
templates:submit| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
Risposte
200 | Submitted (or already at Meta) |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
502 | The submission did not reach Meta (reason in the error message). |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Newsletters
GET/v1/newsletters
List newsletters
Requires scope newsletters:read.
newsletters:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/newsletters
Create a newsletter draft (NEVER sent)
Requires scope newsletters:write. ALWAYS creates only a draft
(status=draft). There is deliberately NO "send now" in this API; an
immediate mass send to all contacts remains a click in the SmartChat app.
Scheduling is possible via POST /newsletters/{id}/schedule with the
SEPARATE scope newsletters:schedule; the sending itself then runs
through the usual safeguards (Meta template approval, opt-in per
recipient, credit and subscription gate). WhatsApp only (channel must
be omitted or whatsapp).
newsletters:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 200 |
subject | string | sì | max length 200 |
content | string | sì | max length 20000 |
channel | string ("whatsapp") | no |
{
"subject": "New this week",
"content": "Hello! This week we have..."
}Risposte
201 | Created |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/newsletters/{id}
Get a newsletter
Requires scope newsletters:read.
newsletters:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/newsletters/{id}
Update a newsletter (button and recipient filter)
Requires scope newsletters:write. At least one of cta or segment
must be in the body.segment filters recipients by tags and is checked against the tags
that ACTUALLY exist; otherwise a typo would silently mean "nobody", which
would only show after sending. segment: null means "all confirmed
contacts" again. cta: null removes the button.
Newsletters that are already sent or currently sending are locked (400).
newsletters:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
cta | object | no | |
cta.text | string | no | max length 200 |
cta.url | string | no | max length 2000 |
segment | object | no | Recipient filter by tags. |
{
"cta": {},
"segment": {}
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
DELETE/v1/newsletters/{id}
Delete a newsletter (draft or scheduled only)
Requires scope newsletters:delete. Sending (sending) and sent (sent)
newsletters cannot be deleted; a sent newsletter is the record of what
went out to contacts (400). Already queued send jobs are removed first.
newsletters:delete| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Deleted |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/newsletters/{id}/schedule
Schedule a newsletter
Requires scope newsletters:schedule; newsletters:write is NOT enough.
Reason: newsletters:write has always explicitly meant "may create
drafts, can never send". If scheduling fell under it, a long-issued key
could trigger a real mass send after an update without the customer ever
granting that.
This route ONLY sets a time. The sending itself then runs through the
usual path and all safeguards: credit gate, opt-in per recipient, Meta
template approval, subscription/payment lock.
Allowed is draft -> scheduled and rescheduling. The time must be in the
future and at most one year ahead.
newsletters:schedule| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Idempotency-Key | header | no | string · Optional. 1-255 printable ASCII characters, no spaces. Same key + same API
key + same account within 24 hours returns the stored first response
(also errors, except 429/503) with header Idempotent-Replayed: true,
without executing again. Different body, path or query -> 422 idempotency_key_mismatch; first request
still running -> 409 idempotency_in_progress (Retry-After: 1); invalid
format -> 400 idempotency_key_invalid.
min length 1 · max length 255 |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
scheduled_at | string | sì | ISO time with zone, e.g. 2026-09-10T09:00:00+02:00. format date-time |
{
"scheduled_at": "2026-09-10T09:00:00+02:00"
}Risposte
200 | Scheduled |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
409 | The current state does not allow the action (e.g. webhook_limit_reached, idempotency_in_progress) |
422 | Idempotency key reused with a different request body or path (idempotency_key_mismatch) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
POST/v1/newsletters/{id}/cancel
Cancel a schedule
Requires scope newsletters:schedule. Only possible while the newsletter
is scheduled; it then returns to draft.
newsletters:schedule| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | Schedule cancelled |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/newsletters/{id}/status
Delivery status of a newsletter
Requires scope newsletters:read. Read-only access to the same counts as
in the SmartChat app (send jobs per status); changes nothing.
newsletters:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Followups
GET/v1/followups
List follow-up sequences
Requires scope followups:read. Changes need followups:write.
CREATING a new step is deliberately not offered: the internal path
generates the text with AI and does not bill this call. Through a public
interface with 120 requests/minute that would be an unpaid lever on model
costs. Text and delay of EXISTING steps can be fully changed.
followups:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/followups/{id}
Get a follow-up sequence
Requires scope followups:read.
followups:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/followups/{id}
Activate, pause or rename a sequence
Requires scope followups:write.status: "active" activates the sequence AND schedules already confirmed
contacts for its steps (future times only). Without this, existing
contacts would never receive newly activated steps.
followups:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
status | string ("active", "paused", "draft") | no | |
name | string | no |
{
"status": "active"
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/followups/steps/{id}
Update a follow-up step (text, subject, delay)
Requires scope followups:write. Delay as delay_minutes,
delay_hours or delay_days.
Two rules apply: the MINIMUM GAP to the other steps of the same sequence
(otherwise a contact would get two messages shortly after each other), and
shifting already queued jobs by the difference. verschobene_auftraege
(shifted jobs) says how many pending messages were moved. Never into the
past: a shortened delay sends from now at the earliest, not
retroactively as a burst.
followups:write| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
id | path | sì | string · format uuid |
Dati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
content | string | no | |
subject | string | no | |
delay_minutes | integer | no | min 0 |
delay_hours | number | no | min 0 |
delay_days | number | no | min 0 |
{
"content": "A quick reminder about your offer.",
"delay_days": 3
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
404 | Not found (or belongs to another account) |
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Settings
GET/v1/settings/profile
Read profile (company name, UI language)
Requires scope settings:read.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/settings/profile
Update profile
Requires scope settings:write. At least one field must be set.
settings:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
name | string | no | max length 120 |
ui_language | string ("en", "de", "it", "fr", "es") | no |
{
"name": "...",
"ui_language": "en"
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/settings/brand
Read brand settings (color, tone, logo, test number)
Requires scope settings:read.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/settings/brand
Update brand settings
Requires scope settings:write. A color set here counts as chosen by
the customer; a later AI build will not overwrite it. test_phone is the
number for newsletter test sends (international format; an empty string
removes it).
settings:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
color | string | no | |
tonality | string | no | max length 300 |
logo_url | string | no | max length 500 |
test_phone | string | no |
{
"color": "...",
"tonality": "...",
"logo_url": "...",
"test_phone": "..."
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/settings/legal
Read imprint/privacy policy URLs
Requires scope settings:read.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/settings/legal
Set imprint/privacy policy URLs
Requires scope settings:write. These are the CUSTOMER's URLs; for the
WhatsApp opt-in the customer is the data controller. URLs on SmartChat's
own domains are therefore rejected with 400.
settings:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
imprint_url | string | no | |
privacy_url | string | no |
{
"imprint_url": "...",
"privacy_url": "..."
}Risposte
200 | Saved |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/settings/followup-timing
Read follow-up send times
Requires scope settings:read.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/settings/followup-timing
Update follow-up send times
Requires scope settings:write. send_time in the format HH:MM,
timezone as an IANA name (e.g. Europe/Berlin). null means "no fixed
time"; timing then stays exact to the second from confirmation. Steps of
other accounts in steps are silently skipped.
settings:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
send_time | string | no | |
timezone | string | no | |
steps | array of object | no | |
steps[].id | string | no | format uuid |
steps[].send_time | string | no |
{
"send_time": "...",
"timezone": "...",
"steps": [
{}
]
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/settings/coexistence
Use the WhatsApp Business app at the same time - read state
Requires scope settings:read. available is only true when a WhatsApp
number is connected.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
PATCH/v1/settings/coexistence
Use the WhatsApp Business app at the same time - toggle
Requires scope settings:write. Enabling requires a connected WhatsApp
number (otherwise 400).
settings:writeDati (body)
| Campo | Tipo | Obbligatorio | Descrizione |
|---|---|---|---|
enabled | boolean | sì |
{
"enabled": true
}Risposte
200 | Updated |
400 | Invalid request (bad_request, idempotency_key_invalid, ...) |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
GET/v1/settings/channels
Read channel state (read only)
Requires scope settings:read. The question an integration should ask
before sending: is a number connected, and is sending currently stopped
(Meta block, invalid access)? While versand_moeglich (sending possible)
is false, NOTHING goes out - no newsletters, follow-ups or automations.
Connecting and disconnecting a WhatsApp number is deliberately not
offered: it is a Meta OAuth flow with an access token, and disconnecting
removes template bindings including the queue.
settings:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Team
GET/v1/team
List team members (read only)
Requires scope team:read. No inviting/removing via this API; account and
permission changes remain exclusive to the SmartChat app.
team:readRisposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Stats
GET/v1/stats
Statistics summary
Requires scope stats:read. The same aggregation as the statistics page in the SmartChat app.
stats:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
range | query | no | string ("7d", "30d", "90d") · default "30d" |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Media
GET/v1/media
List the media library (read only)
Requires scope media:read. No upload via this API: the internal upload
logic (file signature check, SVG sanitizing, EXIF removal, WhatsApp
compression, duplicate detection) is tied to the internal handler.
media:read| Campo | in | Obbligatorio | Descrizione |
|---|---|---|---|
kind | query | no | string ("image", "video") · |
Risposte
200 | OK |
401 | Missing or invalid API key (unauthorized) |
403 | The key lacks the required scope (forbidden, key apikey_scope_fehlt),
the account is blocked (account_blocked), or a plan limit is reached
(limit_reached).
|
429 | Too many requests for this key (120 per minute), code rate_limited |
503 | The account status could not be checked (status_unavailable). The API
deliberately does NOT let the request through (fail-closed); retry in a minute.
|
Meta
GET/v1/openapi.json
This API description as JSON
Public, no authentication. /openapi.yaml returns the same document (JSON is valid YAML).
Risposte
200 | OpenAPI 3.0.3 document |
Domande?
Scrivici a support@smartchat.marketing