Contacts
A contact is a person who writes to a bot in a messenger or in the chat on a website. The methods on this page export your bots' contacts — for example, to move them into a CRM — count them, and create a contact from your own system when you already know the person's messenger ID. For contacts in the dashboard, see Contacts.
You can page through an export in two ways: by pages (page and count, up to 500 contacts per request) or by an offset from the start (offset and limit, up to 1000 contacts per request). getNumberOfContacts tells you how many contacts match.
The methods return contacts of your own bots only. Contacts created while testing a bot in preview are not included in exports or counts.
Contact fields
Every method that returns contacts — here and on the Referrals page — returns them in the same shape.
| Field | Type | Description |
|---|---|---|
id |
number | Contact ID |
bot_id |
number | Bot ID |
phone |
string or null |
Phone number, if the contact shared it or it was set via the API |
email |
string or null |
|
name |
string | Name |
address |
string or null |
Address |
messenger |
string | Where the contact comes from: telegram, max, viber, vk or web (website chat) |
utm |
object | Contact variables whose names start with utm_: {"utm_source": "…"}. If there are none, an empty array [] |
avatar |
string or null |
Link to the contact's photo. A link to a file in storage is temporary — save the file itself, not the link |
telegram_id |
string | Telegram user ID. Telegram contacts only |
telegram_username |
string or null |
Telegram username without @. Telegram contacts only |
max_user_id |
number | MAX user ID. MAX contacts only |
max_username |
string or null |
MAX username. MAX contacts only |
vk_user_id |
number or null |
VK user ID. Present for every contact; null for non-VK contacts |
viber_id |
string | Viber user ID. Viber contacts only |
created_at |
string | When the contact appeared, ISO 8601 in UTC |
unsubscribed_at |
string or null |
When the contact unsubscribed from the bot; null means subscribed |
tags |
array of strings | Contact tags |
variables |
array of objects | Contact variables |
Each variable in variables is an object:
| Field | Description |
|---|---|
id |
Variable ID within the contact |
name |
Variable name |
value |
Value |
type |
What the value holds: 0 — text, 1 — image, 2 — document, 3 — audio, 4 — video. For media, value holds a link to the file — the decodeShortLink method resolves it |
schema_id, deletable, payload |
Internal fields |
For tags and variables in the dashboard, see Tags and variables.
getContacts
Returns your bots' contacts — page by page (20 per page by default) or by an offset from the start.
https://watbot.org/api/v1/getContacts| Parameter | Type | Required | Description |
|---|---|---|---|
bot_id |
number | no | Only contacts of this bot. Without it — contacts of all your bots |
count |
number | no | Contacts per page: 1 to 500. Default 20 |
page |
number | no | Page number, starting from 1. Default 1 |
offset |
number | no | How many contacts to skip from the start, from 0. Switches to offset paging |
limit |
number | no | How many contacts to return in offset paging: 1 to 1000. Default 100. Also switches to offset paging |
date_from |
number | no | Contacts that appeared at or after this moment. Unix time in seconds |
date_to |
number | no | Contacts that appeared at or before this moment. Unix time in seconds |
with |
string | no | Accepted for compatibility, e.g. variables. Changes nothing: tags and variables are always in the response |
Contacts are sorted by ascending id — both page by page and with an offset. If offset or limit is passed, offset paging is used and page and count are ignored.
Page by page
curl -X POST "https://watbot.org/api/v1/getContacts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"bot_id": 12345, "count": 2, "date_from": 1758931200}'
{
"data": [
{
"id": 4815162,
"bot_id": 12345,
"phone": "15550100123",
"email": null,
"name": "Emily Johnson",
"address": null,
"messenger": "telegram",
"utm": {"utm_source": "newsletter"},
"avatar": null,
"telegram_id": "123456789",
"telegram_username": "emily_j",
"vk_user_id": null,
"created_at": "2026-09-28T07:41:12+00:00",
"unsubscribed_at": null,
"tags": ["ordered"],
"variables": [
{"id": 17590475010001, "name": "utm_source", "value": "newsletter", "type": 0, "schema_id": null, "deletable": false, "payload": null},
{"id": 17590475820003, "name": "city", "value": "Austin", "type": 0, "schema_id": null, "deletable": false, "payload": null}
]
},
{
"id": 4815170,
"bot_id": 12345,
"phone": null,
"email": null,
"name": "Michael Brown",
"address": null,
"messenger": "vk",
"utm": [],
"avatar": null,
"vk_user_id": 700123456,
"created_at": "2026-09-29T15:02:47+00:00",
"unsubscribed_at": null,
"tags": [],
"variables": []
}
],
"links": {
"first": "https://watbot.org/api/v1/getContacts?page=1",
"last": "https://watbot.org/api/v1/getContacts?page=38",
"prev": null,
"next": "https://watbot.org/api/v1/getContacts?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 38,
"links": […],
"path": "https://watbot.org/api/v1/getContacts",
"per_page": 2,
"to": 2,
"total": 75
}
}
meta.totalis the total number of matching contacts,meta.last_pageis the number of the last page. To export everything, request pages untillinks.nextbecomesnull. The URLs inlinkscarry none of your parameters exceptpage— sendbot_id,countand the dates again with every request.- New contacts land at the end of the export: sorting by
idkeeps pages from shifting. To keep the export from growing while you page through it, cap it withdate_to. - A
bot_idof a bot that is not yours or does not exist does not cause an error: the list is simply empty.
By offset
Requesting the bot's second hundred contacts:
curl -X POST "https://watbot.org/api/v1/getContacts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"bot_id": 12345, "limit": 100, "offset": 100}'
{
"data": [
{
"id": 4815162,
"bot_id": 12345,
"phone": "15550100123",
"email": null,
"name": "Emily Johnson",
"address": null,
"messenger": "telegram",
"utm": [],
"avatar": null,
"telegram_id": "123456789",
"telegram_username": "emily_j",
"vk_user_id": null,
"created_at": "2026-09-28T07:41:12+00:00",
"unsubscribed_at": null,
"tags": ["ordered"],
"variables": [
{"id": 17590475820003, "name": "city", "value": "Austin", "type": 0, "schema_id": null, "deletable": false, "payload": null}
]
}
],
"meta": {
"offset": 100,
"limit": 100,
"total": 101
}
}
meta.totalis the total number of matching contacts. The export is complete whendataholds fewer contacts thanlimit, oroffset + limithas reachedmeta.total.- For the first batch, pass
offset0or omitoffset.
getNumberOfContacts
Counts your bots' contacts, with the same filters as getContacts.
https://watbot.org/api/v1/getNumberOfContacts| Parameter | Type | Required | Description |
|---|---|---|---|
bot_id |
number | no | Only contacts of this bot. Without it — all your bots |
date_from |
number | no | Contacts that appeared at or after this moment. Unix time in seconds |
date_to |
number | no | Contacts that appeared at or before this moment. Unix time in seconds |
curl "https://watbot.org/api/v1/getNumberOfContacts?bot_id=12345" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
{
"count": 1284
}
The number is in the top-level count field, without a data wrapper.
createOrUpdateContact
Creates a contact in a bot or updates an existing one. The contact is looked up in the bot by its messenger ID: telegram_id, max_id, vk_id or viber_id. If found, its data is updated; if not, a new contact is created.
https://watbot.org/api/v1/createOrUpdateContact| Parameter | Type | Required | Description |
|---|---|---|---|
bot_id |
number | yes | ID of your bot |
messenger |
string | yes | The contact's messenger: telegram, max, viber or vk |
name |
string | yes | Contact name. Replaces the previous name on every call |
telegram_id |
number | for telegram |
Telegram user ID |
telegram_username |
string | no | Telegram username, up to 255 characters |
max_id |
number | for max |
MAX user ID. Can also be passed as max_user_id — the name it has in the response |
max_username |
string | no | MAX username, up to 255 characters |
vk_id |
number | for vk |
VK user ID. Can also be passed as vk_user_id — the name it has in the response |
viber_id |
string | for viber |
Viber user ID, up to 255 characters |
phone |
string | no | Phone in international format: + followed by digits, 9 to 16 characters including the plus — +15550100123. Stored as digits, without +; null is the same as not passing a phone |
email |
string | no | |
address |
string | no | Address, up to 255 characters |
tags |
array of strings | no | Tags, up to 100, each up to 255 characters. They replace all of the contact's tags |
curl -X POST "https://watbot.org/api/v1/createOrUpdateContact" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"bot_id": 12345,
"messenger": "telegram",
"telegram_id": 123456789,
"telegram_username": "emily_j",
"name": "Emily Johnson",
"phone": "+15550100123",
"email": "emily@example.com",
"tags": ["client", "from CRM"]
}'
{
"data": {
"id": 4815162,
"bot_id": 12345,
"phone": "15550100123",
"email": "emily@example.com",
"name": "Emily Johnson",
"address": null,
"messenger": "telegram",
"utm": [],
"avatar": null,
"telegram_id": "123456789",
"telegram_username": "emily_j",
"vk_user_id": null,
"created_at": "2026-10-03T09:15:42+00:00",
"unsubscribed_at": null,
"tags": ["client", "from CRM"],
"variables": []
}
}
{
"message": "Bot not found",
"errors": {
"bot_id": ["Bot not found"]
}
}
Status 201 means the contact was created, 200 means an existing one was updated.
- What changes on an existing contact.
name— always.email,address,phone,telegram_username,max_username— only if passed and not empty: this method cannot clear them.tags— if passed, they replace the whole set of tags; an empty array[]removes all tags. The method does not touch contact variables. - A new contact appears in the bot's contact list with the first message "Created from API" and increases the bot's subscriber count. The bot's scenario is not started, and nothing is sent to the contact.
- The phone is stored as digits, without
+— the same way bot blocks store it.phonein the response has no+either.
Method errors (general ones are under Errors):
| Code | When | Response |
|---|---|---|
404 |
None of your bots has this bot_id — it does not exist or belongs to another account |
{"message": "…", "errors": {"bot_id": ["…"]}} |
422 |
The ID for the chosen messenger is missing, or the phone or email format is invalid | {"message": "…", "errors": {…}} |