Quick start: key, requests, errors
The key, the first request and the first reply to a visitor in four steps, then key scopes, the response format, failure codes, pagination and API limits.
On this page
Addresses #
| What | Address |
|---|---|
| Public API | https://api.widgetchat.ru/api/v1 |
| Widget file | https://api.widgetchat.ru/widget/bozex-support-widget.js |
| Dashboard | https://widgetchat.ru/cabinet |
| Bitrix24 event endpoint | https://widgetchat.ru/b24/event |
| amoCRM event endpoint | https://widgetchat.ru/amocrm/hook/{scope_id} |
| RetailCRM event endpoint | https://widgetchat.ru/retailcrm/hook/{clientId} |
HTTPS only. There is no sandbox: create a separate project in the dashboard and work with it: a workspace keeps it isolated from the live one.
1. Get a key #
Dashboard → the site card → API and webhooks → Create a key. The key is shown once: the database keeps only its fingerprint.
Scopes are chosen when the key is issued: conversations:read, conversations:write, media:read. A method without its scope answers 403 insufficient_scope while the rest keep working with the same key.
2. The first request #
curl -s https://api.widgetchat.ru/api/v1/conversations?status=open&limit=5 \
-H "Authorization: Bearer wck_your_key"{
"data": [
{
"id": "6c82f8e2-2ee2-4387-8c9b-34d164b18176",
"status": "open",
"channel": "app",
"visitor": {"id": "u_8f1c…", "name": "John", "email": "john@example.com"},
"source": "widget",
"createdAt": "2026-08-22T09:14:58.113Z",
"lastMessageAt": "2026-08-22T09:15:04.281Z",
"lastReadAt": null
}
],
"nextCursor": "2026-08-22T09:14:58.113Z",
"hasMore": true
}3. Reply to a visitor #
curl -s -X POST https://api.widgetchat.ru/api/v1/conversations/6c82f8e2-…/messages \
-H "Authorization: Bearer wck_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: reply-4417" \
-d '{"content": "Your order is on the way, delivery tomorrow before 2 pm"}'201 {"data": {"id": "7735af47-…", "status": "queued", "direction": "outgoing",
"createdAt": "2026-08-22T09:15:04.281Z"}}Idempotency-Key makes a retry safe: the same key returns 200 and duplicate: true instead of a second message in the conversation.
4. Subscribe to events #
Dashboard → API and webhooks → Add an address. The signing secret is shown once. The Test button sends a webhook.test event, which shows you your own signature and your handler's response code.
The handler has to answer 2xx within 20 seconds. Move the work into your own queue: a slow answer counts as a failure and causes a retry.
The key: where to keep it and how to revoke it #
Every request carries the Authorization: Bearer wck_… header. A key is issued for one connected site and opens the conversations of that site only: a neighbouring connection's conversation is not found with it even by an exact id.
The database keeps only the fingerprint of the key. A lost key is not recovered: it is revoked and issued again. A revoked key stops opening anything immediately, while the record stays with a revokedAt mark.
Authorization: Bearer wck_cZLLSCqi7pQ2m4E1vN…The key is a server key. It must not go into your page code: any visitor would read it there and get access to every conversation of the site.
Key scopes #
| Scope | Methods |
|---|---|
| conversations:read | GET /conversations, GET /conversations/{id}, GET /conversations/{id}/messages |
| conversations:write | POST /conversations/{id}/messages, POST /conversations/{id}/close |
| media:read | GET /media/{id} |
Browser requests and CORS #
The public API deliberately serves no CORS headers, so a request from a visitor's browser will not pass. The widget uses another entrance: a signed window token issued by the gateway.
Authentication failures #
| HTTP | code | When |
|---|---|---|
| 401 | unauthorized | no header, wrong key or a revoked one |
| 403 | insufficient_scope | the key has no scope for this method |
| 429 | rate_limit_exceeded | more than 300 requests per minute per key |
The response envelope #
A successful answer always puts the content into data, even when it is a single object. Lists get nextCursor and hasMore next to it. A failure arrives in the same envelope with an error field carrying a machine code and an explanation.
Every response carries Cache-Control: no-store: they contain someone's conversation.
{"data": { … }}
{"data": [ … ], "nextCursor": "2026-08-22T09:15:04.281Z", "hasMore": true}
{"error": {"code": "validation_error", "message": "content must not exceed 4096 characters"}}All failure codes #
| HTTP | code | When |
|---|---|---|
| 400 | validation_error | the body did not parse or a value does not fit |
| 401 | unauthorized | no key, revoked or belonging to someone else |
| 403 | insufficient_scope | the key has no scope for the method |
| 404 | not_found | no such conversation, or it belongs to another site |
| 409 | conversation_closed | the conversation is closed, the visitor will not see the reply |
| 409 | no_visitor | the conversation has no widget visitor |
| 413 | file_too_large | the file behind the link is over the limit |
| 429 | rate_limit_exceeded | rate limit exceeded, see Retry-After |
| 502 | file_fetch_failed | the file behind your link did not download |
| 503 | storage_unavailable | the database or Redis is unreachable, retry later |
Pagination #
Pagination is cursor based, not page numbers: while the first page is being read visitors keep writing, and numbering would push some conversations past the reader. The cursor is the time of the last shown item in RFC 3339 with nanoseconds.
Take nextCursor from the answer and pass it as the cursor parameter while hasMore is true.
| Field | Type | Req. | Description |
|---|---|---|---|
| limit | int | no | page size: 25 by default, 100 at most |
| cursor | string | no | continuation: the nextCursor value of the previous answer |
Limits #
| What | How much |
|---|---|
| Requests per key | 300 per minute, then 429 with Retry-After |
| Page size | 25 by default, 100 at most |
| Reply length | 4096 characters |
| Request body | 256 KB |
| File behind a link | 50 MB |
| Signed attachment link lifetime | 1 hour |
| Waiting for your webhook handler | 20 seconds |
| Webhook delivery attempts | 3, a 5 second pause doubling after that |
| Webhook signature window | 5 minutes |
What next #
Full method signatures are on the Conversations, messages and attachments page. The event format and the signature check are in Webhooks. If you need a ready connector instead of the API, see the Bitrix24 and RetailCRM pages. The amoCRM connection is described separately: it starts working once amoCRM support issues the service its channel.