Press Enter.
Get your data.
REST API /api/v1, 53 scopes, 239 endpoints, 11 webhook events and a JS API for the widget. Chats, contacts, AI, knowledge base, tickets and billing — whatever the dashboard does, your code can do too.
# press Enter or the mark on the right $ curl -H "Authorization: Bearer sb_••••" \ https://smartbtn.me/api/v1/chats?limit=1
Quickstart
Three steps from zero to the first answer. Every request is tied to one widget and authenticated with a bearer token.
- Issue a tokenDashboard → API tokens: a name, an optional expiry and the scopes you need. A token belongs to exactly one widget. The plain‑text token is shown once; Smartbtn stores only a one‑way hash, so a lost token cannot be recovered — only revoked and re‑issued.
- Turn on the widget APIIn the widget settings, turn on «Allow widget API (JS and REST)». Issuing a token does not flip this switch for you.
- Send the first requestThe token goes only into the
Authorizationheader — never into the URL.
# list the widget's chats curl -H "Authorization: Bearer $SMARTBTN_TOKEN" \ https://smartbtn.me/api/v1/chats
// 200 OK · cursor pagination { "data": [ { "id": 48211, "status": "open", "last_message_at": "2026-10-17T09:41:12+03:00" }, … ], "next_cursor": "eyJpZCI6NDgyMTB9" // null — on the last page }
https://smartbtn.me/api/v1 is the primary API endpoint for all project data. Always send requests over HTTPS and never forward the token on redirects.401 or 403 with an RFC‑7807 application/problem+json body — see Errors.Authentication
Three paths, depending on who calls whom. Access is deny‑by‑default: no scope — no call.
Every request carries Authorization: Bearer . On the server the token resolves to one widget and its scopes.
Outgoing requests are signed with a per‑tenant secret: X‑Smartbtn‑Signature. An extra bearer credential can be added if your side needs one.
POST /v1/ai/replies uses its own signed frame, pinned to your AI operator and widget and keyed by a durable causation_id.
The switch people forget
«Allow widget API (JS and REST)» in the widget settings opens both the REST API and the widget JS API. Issuing a token does not enable it. The scopes of an existing key can be edited in the dashboard (API tokens → key → Edit scopes) without re‑issuing it — integrations keep working.
Presets
| Preset | Scopes | When |
|---|---|---|
| AI setup 9 | widget:read · widget:write · ai:read · ai:write · ai:apply · kb:read · kb:write · files:write · stats:read | Your AI app configures the widget: assistant, knowledge base, texts. Replaces the whole scope selection. |
| Read‑only (example set) | chats:read · messages:read · contacts:read · stats:read | Dashboards, BI, exports. |
| Helpdesk bridge (example set) | chats:read · messages:read · messages:write · webhooks:write · support:read | Mirror dialogs and tickets into your CRM. |
ai:credentials:write only when the owner authorizes provider key setup. Account, billing and partner rights are not needed for AI setup. The key is shown once — revoke it when the setup is done.Scopes
53 route scopes, plus one conditional and one reserved. A request succeeds only if the token holds the route scope (or a listed alternative).
| Scope | Grants |
|---|---|
| chats · 2 | |
| chats:read | Read chats and their metadata |
| chats:write | Close a chat, request a rating, transfer, claim, attach or detach an agent |
| messages · 2 | |
| messages:read | Read a chat's message history |
| messages:write | Send messages, typing indicators and read receipts as an agent |
| contacts · 2 | |
| contacts:read | Read contacts |
| contacts:write | Update contact fields and attributes |
| agents · 3 | |
| agents:read | Read agents and their presence |
| agents:writesensitive | Invite, update, suspend, restore or remove agents; an invitee sees every chat of the widget |
| agents:events:read | Read an agent's event log and per‑agent metrics |
| tags · 2 | |
| tags:read | Read tags |
| tags:write | Attach tags to a contact |
| files · 2 | |
| files:read | Download an uploaded file |
| files:write | Upload a new file |
| stats · 1 | |
| stats:read | Read aggregate chat, message and rating stats |
| channels · 3 | |
| channels:read | Read a custom channel's online status |
| channels:write | Deliver an inbound message on a custom channel |
| channels:register | Register a new custom channel (installed apps only) |
| webhooks · 2 | |
| webhooks:read | List webhook subscriptions |
| webhooks:write | Create, delete or redeliver a subscription |
| quick_phrases · 2 | |
| quick_phrases:read | Read an agent's quick phrases |
| quick_phrases:write | Create, edit or delete quick phrases |
| ratings · 1 | |
| ratings:read | Read visitor ratings and which agent each one scores |
| responder · 2 | |
| responder:injectsensitive | Inject a reply into a live chat as an external AI operator or bot |
| responder:escalateconditional | For POST /v1/ai/replies: caller‑directed handoff via escalate=true |
| widget · 2 | |
| widget:read | Read widget appearance, behaviour and embed settings |
| widget:write | Update widget settings and purge the widget cache |
| departments · 2 | |
| departments:read | Read departments, their agents and schedules |
| departments:write | Create, update or delete departments and schedules |
| messengers · 2 | |
| messengers:read | Read which messengers are connected (never credentials) |
| messengers:writesensitive | Connect or disconnect a messenger; writes provider credentials |
| ai · 4 | |
| ai:read | Read AI assistants, their configuration and alerts |
| ai:write | Create and update assistants, AI settings and AI operators, persona and prompt included |
| ai:credentials:writesensitive | Store third‑party LLM provider credentials (BYOK) |
| ai:apply | Approve an improvement that rewrites a live assistant's persona |
| kb · 2 | |
| kb:read | Read knowledge‑base rules and ingested sources |
| kb:write | Create, update or delete KB rules and sources |
| transcripts · 1 | |
| transcripts:read | Export a chat transcript |
| account · 2 | |
| account:read | Read the account profile and all its legal entities |
| account:write | Update only the account's name, surname and phone |
| billing · 2 | |
| billing:read | Read the widget's billing records and legal entities |
| billing:write | Create, update, delete legal entities; issues no invoices, moves no money |
| partners · 2 | |
| partners:read | Read partner and referral data |
| partners:withdrawreserved | Reserved: no payout operation uses it today |
| support · 4 | |
| support:read | Read tickets, active chats, their messages and own audited actions |
| support:replysensitive | Answer a customer as the support operator |
| support:write | Claim or release a chat, close without reply, reopen |
| support:tickets:close | Only close a ticket — nothing else |
| marketing · 2 | |
| marketing:read | Read marketing campaigns: banners, popups, email |
| marketing:write | Create and edit campaigns, change status, start an email send |
| broadcasts · 2 | |
| broadcasts:read | Read messenger broadcasts (WhatsApp, Telegram, Messenger, Viber, VK, MAX) |
| broadcasts:write | Create, edit and start a broadcast |
| problems · 2 | |
| problems:read | Read customer‑problem clusters and settings |
| problems:write | Change settings and cluster status: new, in progress, resolved, recurring |
| invitations · 2 | |
| invitations:read | Read invitation rules, A/B variants, templates and funnel |
| invitations:write | Create, edit, enable or delete rules and templates |
Endpoints
The whole public surface in one list. Filter by resource, search by path, click a row to copy a ready curl.
ai Assistants, operators, keys, learning, marketplace54
chats Dialogs, messages, transfer, ratings18
kb Knowledge base: rules, crawler, files, search16
agents Agents, invitations, metrics14
messengers Messengers, social networks & marketplace channels13
billing Balance, subscriptions, invoices, entities12
support Support agent: tickets and chats12
widget Settings, language, translations, skins, cache12
channels Custom channels8
external‑operators Your bot as an operator8
webhook‑subscriptions Webhook subscriptions8
broadcasts Messenger broadcasts7
departments Departments and schedule7
invitations Smart invitations7
marketing Marketing campaigns7
partner Partner program7
wishes Wishes for the AI7
contacts Contacts and tags5
problems Customer problem analytics4
quick‑phrases Quick phrases4
compat Migration compatibility3
stats Statistics3
account Account2
files Files2
ratings Ratings1
tags Tags1
v1 1
webhook‑events Event catalog1
Paths are relative to https://smartbtn.me/api. Writes need Content‑Type: application/json and X‑Smartbtn‑Idempotency‑Key. The compat group is a compatibility layer for teams moving from another chat platform.
Webhooks
A signed JSON POST to your URL whenever a subscribed event happens. Manage subscriptions via /v1/webhook‑subscriptions or in the dashboard.
{
"id": "evt_01JAB3K9Q7",
"type": "ticket.created",
"data": {
"button_guid": "b_3f9c2e",
"ticket_number": 10482,
"chat_id": 48211,
"client_id": 9134,
"reason": "human_request",
"priority": "high",
"sla_hours": 4,
"source": "chat",
"created_at": "2026-10-17T10:15:00+03:00"
}
}reason: human_request | billing | ai_unresolved | action_request | …; priority: high | normal; source: chat | app | site. Read the ticket and its dialog with GET /v1/support/tickets/{number}.
Delivery headers
| X‑Smartbtn‑Event | Event type, e.g. message.created. |
| X‑Smartbtn‑Signature | sha256=v1: of the raw body. |
| X‑Smartbtn‑Idempotency‑Key | One value per event, stable across retries. Dedupe on it. |
| X‑Smartbtn‑Delivery | One value per delivery attempt — for your logs. |
| X‑Smartbtn‑Timestamp | Unix time of sending. Informational, not signed. |
Signature verification
HMAC‑SHA256 of the raw body (bytes as received, before JSON parsing) with your endpoint secret; compare in constant time. The secret is shown once, when the subscription is created; rotate it with POST /v1/webhook‑subscriptions/{id}/rotate‑secret.
// Node.js · example, the secret is a placeholder import crypto from 'node:crypto'; function verify(rawBody, header, secret) { const expected = 'sha256=v1:' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex'); const a = Buffer.from(expected), b = Buffer.from(header || ''); return a.length === b.length && crypto.timingSafeEqual(a, b); }
// PHP $expected = 'sha256=v1:' . hash_hmac('sha256', file_get_contents('php://input'), $secret); if (!hash_equals($expected, $_SERVER['HTTP_X_SMARTBTN_SIGNATURE'] ?? '')) { http_response_code(401); exit; }
Retries and order
- Up to 4 attempts (the first send plus 3 retries), backoff
min(60, 2^attempt × 5)s — about 10, 20, 40 s. - Non‑2xx or a timeout counts as a failed attempt. Failed deliveries can be resent with
POST /v1/webhook‑subscriptions/{id}/redeliver— same idempotency key, new delivery id. - Delivery is at‑least‑once and not ordered. Payloads are minimal — ids, not full records; fetch details via the REST API.
JS API
Pass what you already know about the visitor straight to the agent. Calls are accepted only from the domain set in the widget settings.
smartbtn_widget_api.setContactInfo(info)
Sets the visitor's contact data. The agent sees it as if the visitor filled in the intro form. Name, phone and email play a special role in Smartbtn — hence a separate method.
| Name | Type | Description |
|---|---|---|
| name | string | Visitor name |
| string | Visitor email | |
| phone | string | Visitor phone |
| description | string | Any extra info about the client |
Smartbtn_api.setClientInfo({ name: "Alex Morgan", email: "email@example.com", phone: "+17584987855", description: "Description text" });
smartbtn_widget_api.setCustomData(fields)
Any extra data for the info panel on the right of the agent app. Call it as often as you like — in an open dialog the panel updates in real time. Fields are shown in array order.
| Name | Type | Description |
|---|---|---|
| fields | array | List of data fields |
| field.title | string | Heading above the field |
| field.content | string | Field content; tags are escaped |
| field.link | string | URL opened on click |
Smartbtn_api.setClientCustomData([ { title: "Order", content: "#10482 · 3 items", link: "https://shop.example/orders/10482" }, { title: "Actions", content: "Open customer profile", link: "https://crm.example/c/9134" } ]);
smartbtn_widget_api.setSkin(skin, opts) · open() · close()
Switch the widget theme on the fly without reloading the page (classic, minimal, capsule, liquid) or control the chat window programmatically. For permanent per‑project customization, pass the same fields to PATCH /v1/widget/settings.
// JS API · switch skin on the page in real time smartbtn_widget_api.setSkin("minimal"); smartbtn_widget_api.setSkin("capsule", { capsuleTitle: "Smartbtn AI", capsuleSubtitle: "Replies in ~1 s" }); // REST API · PATCH /v1/widget/settings (scope widget:write) { "skin": "minimal", "widget_header_align": "center", "widget_show_operator_avatars": false, "widget_show_tabs_bar": false, "chat_bg": "#FAF8F5", "capsule_title": "Smartbtn AI", "capsule_subtitle": "Online 24/7" }
widget_api_contact_sync on, these calls also fire the contact.updated webhook.Support‑agent API
An automated support agent works the ticket queue and customer chats: takes a chat, answers as your human support operator, closes the ticket. Off until the widget owner turns it on.
- The owner enables itLists the tokens allowed to act as support agents and the IPs they may call from.
- Read the queue
GET /v1/support/tickets·GET /v1/support/chats - Lease a chat
POST …/chats/{id}/claim·…/release - ReplyPlain text, links only to the widget's allowed hosts.
201only once the message is stored. - Close or reopen
POST …/tickets/{number}/close·…/reopen
| Scope | Allows |
|---|---|
| support:read | Tickets, active chats, messages labelled client / ai / support / system, own audited actions |
| support:write | Claim / release a chat, close without reply, reopen |
| support:reply | Answer the customer as the support operator (sensitive) |
| support:tickets:close | Only close a ticket — for a «question solved» button on your backend |
curl -X POST https://smartbtn.me/api/v1/support/chats/48211/reply \ -H "Authorization: Bearer $AGENT_TOKEN" \ -H "Content-Type: application/json" \ -H "X-Smartbtn-Idempotency-Key: $(uuidgen)" \ -d '{"text":"Done, access has been restored."}'
AI API
Everything the AI section of the dashboard does: assistants, your own provider keys, knowledge base, self‑learning with rollback, wishes, problems, demand signals and an assistant inside your app.
Several assistants with their own role and language, a test before going live, operators named per language.
- GET/v1/ai/assistants
- POST/v1/ai/assistants/{id}/test
- PATCH/v1/ai/operators/{id}
- POST/v1/ai/handoff
Claude, ChatGPT, DeepSeek, Gemini, Mistral, regional LLMs or any OpenAI‑compatible. Models are listed per key.
- GET/v1/ai/credentials
- POST/v1/ai/credentials
- GET/v1/ai/credentials/{id}/models
A crawler for your site, PDF and DOCX uploads, rules, search and indexing status.
- PUT/v1/kb/crawler
- POST/v1/kb/uploads
- POST/v1/kb/rules
- GET/v1/kb/search
Tuning runs, cycles, history, persona versions with rollback and a kill switch.
- POST/v1/ai/learning/tune
- GET/v1/ai/learning/cycles
- POST/v1/ai/learning/persona‑versions/{version}/revert
- GET/v1/ai/learning/kill‑switch
A wish in plain words → a side‑effect‑free preview → approve, reject or revert.
- POST/v1/wishes
- GET/v1/wishes/{id}/preview
- POST/v1/wishes/{id}/approve
- POST/v1/wishes/{id}/revert
Problem clusters with statuses and a monthly spend cap; what customers asked for that you do not offer.
- GET/v1/problems
- PATCH/v1/problems/settings
- POST/v1/problems/{id}/status
- GET/v1/ai/demand‑signals
Your backend pushes customer status (registered, paid, customer since, service state) in an HMAC‑signed request — the AI weighs it when answering and escalating.
- POST/v1/ai/customer‑status
- POST/v1/ai/tickets
- GET/v1/ai/alerts
Dialog turns, account linking, speech‑to‑text and text‑to‑speech, app tickets — over a signed integration.
- POST/v1/ai/assistant/turn
- POST/v1/ai/assistant/account‑link
- POST/v1/ai/assistant/speech‑to‑text
- POST/v1/ai/assistant/text‑to‑speech
Ready assistants by niche: café, clinic, shop, car service. Apply in one request.
- GET/v1/ai/marketplace/templates
- POST/v1/ai/marketplace/templates/{slug}/apply
Your own bot answers chats: async replies, handoff, tests and lifecycle.
- POST/v1/ai/replies
- POST/v1/external‑operators/{public_id}/tests
- POST/v1/external‑operators/{public_id}/lifecycle
Rate limits
Per token, two counters: reads and writes are counted apart, so polling never eats the write budget.
| X‑RateLimit‑Limit | Size of the counter this request was counted in (600 or 120) |
| X‑RateLimit‑Remaining | Requests left in the current window |
| X‑RateLimit‑Reset | When the window resets |
| Retry‑After | On 429: seconds to wait |
HTTP/1.1 429 Too Many Requests Content-Type: application/problem+json Retry-After: 12 X-RateLimit-Limit: 120 X-RateLimit-Remaining: 0 { "status": 429, "title": "Too Many Requests", "reason": "rate_limited" }
/v1/ai/assistant/tickets/status and /v1/ai/assistant/account‑link have their own counters; the support‑agent API can have a per‑widget override.
Errors
Every error is RFC‑7807 application/problem+json: a machine‑readable status and reason, a human‑readable detail.
HTTP/1.1 403 · Content-Type: application/problem+json { "type": "https://smartbtn.me/problems/forbidden", "title": "Forbidden", "status": 403, "detail": "Token lacks scope chats:write.", "required_scopes": [ "chats:write" ], "hint": "Dashboard → API tokens → key → Edit scopes" }
The body names required_scopes and where to grant them. No need to re‑issue the key.
| Status | Meaning |
|---|---|
| 400 | Malformed request or a required idempotency key is missing |
| 401 | No token, invalid or revoked token |
| 403 | The token lacks the scope; the body adds required_scopes and where to grant it |
| 404 | Not found in this widget |
| 405 | Method not allowed — stop and report; do not look for alternate writes |
| 409 | Idempotency key reused within 24 h, or a state conflict |
| 422 | Validation failed (e.g. a read‑only field was sent) |
| 429 | Rate limit; respect Retry‑After |
Idempotency
Networks fail. A key makes a retried write safe: the same operation is never applied twice.
- Send
X‑Smartbtn‑Idempotency‑Keyon every POST / PATCH / PUT / DELETE: a new UUID for a new operation, the same key for a retry of the same one. - Operations marked
x‑idempotency: requiredin OpenAPI: no key → 400, the key reused within 24 hours → 409 (not a cached success). - Not sure it went through? Read the state first. Never change the key automatically; respect Retry‑After.
- A
502from an upstream provider releases the key — retry with the same key.
KEY=$(uuidgen) curl -X PATCH https://smartbtn.me/api/v1/widget/settings \ -H "Authorization: Bearer $SMARTBTN_TOKEN" \ -H "Content-Type: application/json" \ -H "X-Smartbtn-Idempotency-Key: $KEY" \ -d '{"language":"ru"}' # network error? repeat with the same $KEY
Changelog
Changes to the public API and webhooks in 2026. Everything below is additive and stays in v1.
New live event ticket.created. GET /v1/support/tickets answers any key with support:read until a support agent is configured. Key scopes are editable without re‑issuing. 403 gains required_scopes.
POST/PATCH /v1/ai/operators accept name_i18n; default names are translated into the widget language; predictable greeting choice.
Reads — 600 per minute, writes — 120. Polling no longer eats the write budget. X‑RateLimit-* describe the counter that was used.
Chats with activity since an instant, however old they are. Every chat now carries last_message_at.
chat.account.email_requested — the chat awaits the address; agents must not start another code flow.
Close a ticket and nothing else — for a «question solved» button on your backend.
Filters has_client_messages=1 and q (2–100 characters).
POST /v1/ai/assistant/account‑link and /revoke. Off until the owner enables it.
Rules are embedded with the widget key or an enabled assistant key; a 502 releases the idempotency key.
The account is visible while the ticket is open and for 7 days after.
New /v1/support group: queue, chats, leases, replies, closing and reopening tickets. Off until the owner enables it.
Fields code_pending, code_expires_at, last_code_result and last_code_at.
WordPress plugin
The widget on a WordPress site without touching the theme code.
- Downloadthe plugin archive to your computer.
- InstallPut the unpacked folder into
wp‑content/plugins/— or upload it in the WordPress admin. - ActivateA Smartbtn item appears in the menu.
- Paste the tokenCopy the security token from the widget settings in your dashboard.
When you change your password, the security token changes too and the old one stops working — paste the new one into the plugin.
Code samples
List every chat with activity since your last poll — following the cursor to the end.
# first page curl -G https://smartbtn.me/api/v1/chats \ -H "Authorization: Bearer $SMARTBTN_TOKEN" \ --data-urlencode "updated_since=2026-10-17T09:00:00+03:00" # next — with next_cursor from the response curl -G https://smartbtn.me/api/v1/chats \ -H "Authorization: Bearer $SMARTBTN_TOKEN" \ --data-urlencode "cursor=eyJpZCI6NDgyMDd9"