Assistly REST API
Read your leads and conversations and manage your bot's Questions & answers from your own code, with keys you make and revoke yourself.
Pull your leads and conversations into your own CRM, data warehouse or app, and keep your bot's Questions & answers in sync from your own code. The REST API is part of the Premium plan.
Get a key
- In your dashboard open Integrations and find REST API.
- Give the key a name (the tool that will use it) and pick what it may do.
- Copy the key right away. It starts with
ak_live_and is shown only once: we keep only a fingerprint of it, so nobody can show it to you again. Lost it? Revoke it and make a new one.
Only the account admin can make and revoke keys. You can have up to 10 active keys. Each key belongs to one website in your account and only ever sees that website's data.
Authentication
Send the key in the Authorization header of every request, over https:
Authorization: Bearer ak_live_YOUR_KEY
curl https://assistlychat.com/api/v1/leads \
-H "Authorization: Bearer ak_live_YOUR_KEY"
The key decides the account. A company id in the address, the query or the body is ignored, so a key can never read or change another account.
Scopes
leads:readlets the key list leads and read one lead.conversations:readlets the key list conversations and read one with its messages.qa:writelets the key list, add, change and delete pairs in your Questions & answers.
A request outside the key's scopes answers 403 with the code insufficient_scope.
List leads
GET /api/v1/leads returns your leads, newest first.
Query: limit (1 to 100, default 50), cursor (from the previous page) and since (an ISO 8601 date or time: only leads created or updated at or after it).
curl "https://assistlychat.com/api/v1/leads?limit=2&since=2026-10-01" \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{
"data": [
{
"id": "6713f0c2a1b2c3d4e5f60718",
"name": "Maria Lopez",
"email": "maria@example.com",
"phone": "5125550100",
"status": "new",
"conversationId": "3f1c9e2a-7b4d-4e0a-9c1f-2d8b6a5e4f30",
"lastMessage": "Can someone come out this week to look at a leak?",
"createdAt": "2026-10-18T15:04:11.000Z",
"updatedAt": "2026-10-18T15:06:40.000Z",
"language": "en",
"afterHours": false,
"source": "website",
"referredBy": null,
"verifiedUser": false,
"booking": null,
"attribution": { "utmSource": "google", "utmMedium": "cpc", "utmCampaign": null, "referrerHost": "google.com", "landingPath": "/repairs" }
}
],
"has_more": true,
"next_cursor": "eyJ0IjoiMjAyNi0xMC0xOFQxNTowNDoxMS4wMDBaIiwiaSI6IjY3MTNmMGMy..."
}
Lead status is one of new, contacted, won or lost.
Get a lead
GET /api/v1/leads/{id} returns one lead in the same shape, inside data.
curl https://assistlychat.com/api/v1/leads/6713f0c2a1b2c3d4e5f60718 \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{ "data": { "id": "6713f0c2a1b2c3d4e5f60718", "name": "Maria Lopez", "email": "maria@example.com", "status": "new" } }
(Shortened here: the answer carries every field shown in the list.)
List conversations
GET /api/v1/conversations returns one row per conversation, the most recent message first. Same limit, cursor and since (here: conversations with a message at or after that moment).
curl "https://assistlychat.com/api/v1/conversations?limit=20" \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{
"data": [
{
"id": "3f1c9e2a-7b4d-4e0a-9c1f-2d8b6a5e4f30",
"startedAt": "2026-10-18T15:03:52.000Z",
"lastMessageAt": "2026-10-18T15:07:02.000Z",
"messageCount": 6,
"contact": { "name": "Maria Lopez", "email": "maria@example.com", "phone": "5125550100" },
"language": "en",
"channel": "website",
"status": "open",
"needsHuman": false,
"aiActive": true,
"summary": "Wants a plumber this week for a leak under the sink.",
"test": false
}
],
"has_more": false,
"next_cursor": null
}
channel is website or whatsapp. test is true for chats your own team ran as a test.
Get a conversation
GET /api/v1/conversations/{id} returns the conversation with every message in order. from is visitor, ai, team or system. A team reply sent in the visitor's language also carries the team's own words in originalText.
curl https://assistlychat.com/api/v1/conversations/3f1c9e2a-7b4d-4e0a-9c1f-2d8b6a5e4f30 \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{
"data": {
"id": "3f1c9e2a-7b4d-4e0a-9c1f-2d8b6a5e4f30",
"startedAt": "2026-10-18T15:03:52.000Z",
"lastMessageAt": "2026-10-18T15:07:02.000Z",
"contact": { "name": "Maria Lopez", "email": "maria@example.com", "phone": "5125550100" },
"status": "open",
"messages": [
{ "from": "visitor", "text": "Can someone come out this week to look at a leak?", "at": "2026-10-18T15:03:52.000Z" },
{ "from": "ai", "text": "Yes, we have openings on Wednesday and Thursday. What is the best number to reach you?", "at": "2026-10-18T15:03:55.000Z" },
{ "from": "team", "name": "Dana", "text": "Hi Maria, Dana here. Thursday at 10 works for us.", "at": "2026-10-18T15:07:02.000Z" }
]
}
}
List Q&A pairs
GET /api/v1/qa returns the pairs in your bot's Questions & answers, with an id for each. filled is false while an answer still has a [placeholder] in square brackets: the bot does not use that pair until it is filled. Free text notes you typed in the dashboard are kept but not listed.
curl https://assistlychat.com/api/v1/qa \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{
"data": [
{ "id": "qa_9b1f0c3a7d2e4f58", "question": "Do you offer weekend appointments?", "answer": "Yes, Saturdays from 9 to 1.", "filled": true }
],
"count": 1,
"max": 150
}
Add a Q&A pair
POST /api/v1/qa with a JSON body. The question can be up to 300 characters and the answer up to 2,000. Your bot uses the new pair in its next answer.
curl -X POST https://assistlychat.com/api/v1/qa \
-H "Authorization: Bearer ak_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Do you offer weekend appointments?","answer":"Yes, Saturdays from 9 to 1."}'
HTTP/1.1 201 Created
{ "data": { "id": "qa_9b1f0c3a7d2e4f58", "question": "Do you offer weekend appointments?", "answer": "Yes, Saturdays from 9 to 1.", "filled": true } }
A question that is already there answers 409 duplicate_question with its id, so you can change it instead.
Change a Q&A pair
PUT /api/v1/qa/{id} with question, answer or both. The id comes from the question, so a new question gives the pair a new id (it is in the answer).
curl -X PUT https://assistlychat.com/api/v1/qa/qa_9b1f0c3a7d2e4f58 \
-H "Authorization: Bearer ak_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"answer":"Yes, Saturdays from 9 to 2."}'
{ "data": { "id": "qa_9b1f0c3a7d2e4f58", "question": "Do you offer weekend appointments?", "answer": "Yes, Saturdays from 9 to 2.", "filled": true } }
Delete a Q&A pair
DELETE /api/v1/qa/{id} removes that one pair from your Questions & answers. Every other pair, your notes and the rest of your bot's knowledge stay as they are.
curl -X DELETE https://assistlychat.com/api/v1/qa/qa_9b1f0c3a7d2e4f58 \
-H "Authorization: Bearer ak_live_YOUR_KEY"
{ "deleted": true, "id": "qa_9b1f0c3a7d2e4f58" }
Pagination
Lists return up to limit rows plus has_more and next_cursor. To get the next page, send the same request with cursor set to next_cursor, as it is. When has_more is false, next_cursor is null and you have everything. To sync new leads every hour, keep the time of your last run and send it as since.
curl "https://assistlychat.com/api/v1/leads?limit=100&cursor=eyJ0IjoiMjAyNi0xMC0xOFQxNTowNDoxMS4wMDBaIiwiaSI6IjY3MTNmMGMy..." \
-H "Authorization: Bearer ak_live_YOUR_KEY"
Rate limits
Each key can make 60 requests a minute, and each network 120 a minute. Over the limit the API answers 429 with the code rate_limited and a Retry-After header with the seconds to wait.
HTTP/1.1 429 Too Many Requests
Retry-After: 37
{ "error": { "code": "rate_limited", "message": "This key is limited to 60 requests a minute. Wait for the seconds in Retry-After and try again." } }
Errors
Every error is JSON with a code you can check in your code and a message you can read:
{ "error": { "code": "insufficient_scope", "message": "This key can't do that. It needs the qa:write scope (Write Q&A).", "requiredScope": "qa:write" } }
- 400
invalid_parameter,invalid_cursororinvalid_json: something in the request is not right; the message says what. - 401
missing_key: no Authorization header. - 401
invalid_key: the key is wrong or does not exist. - 401
revoked_key: the key was revoked under Integrations. - 403
insufficient_scope: the key does not have the scope this needs. - 403
plan_required: the account is not on Premium right now. Keys start working again after an upgrade. - 404
not_found: no such lead, conversation, pair or endpoint in this account. - 409
duplicate_question: that question is already in your Questions & answers. - 422
limit_reached,too_longorknowledge_full: the change would pass a limit of your bot's knowledge. - 429
rate_limited: see Rate limits. - 500
server_error: something went wrong on our side; try again in a minute.
Questions
Write to support@assistlychat.com and we will help you connect.