Messages
Send WhatsApp messages to your contacts. You can identify the contact by phone number or by ID.
POST /v1/message/text
Sends a text message. If the contact doesn't exist, it is created automatically.
| Parameter | Type | Required | Description |
text | string | Yes | Message body. |
number | string | Conditional | Contact phone in international format, without the '+' sign. Required if contactid is not provided. |
contactid | string | Conditional | Contact ID (UUID). Alternative to number. |
conchi_user_id | string | No | ID of an AI user in the organization, to attribute the message to that agent. |
Example request
curl -X POST https://api.manycontacts.com/v1/message/text \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "number": "34600111222", "text": "Hola 👋" }'
Example response
{ "id": "8f3c...", "error": null }
POST /v1/message/media
Sends a file (image, audio, video or document) as a multipart attachment. The type is detected from the file.
| Parameter | Type | Required | Description |
number | string | Yes | Contact phone in international format, without the '+' sign. Required if contactid is not provided. |
file | file (multipart) | Yes | File to send (multipart/form-data). |
caption | string | No | Text accompanying the file. |
Example request
curl -X POST https://api.manycontacts.com/v1/message/media \
-H "apikey: TU_API_KEY" \
-F "number=34600111222" \
-F "caption=Tu factura" \
-F "file=@factura.pdf"
Example response
{ "id": "8f3c...", "error": null }
POST /v1/message/note
Adds an internal note to the contact's conversation (not sent to the customer).
| Parameter | Type | Required | Description |
number | string | Yes | Contact phone in international format, without the '+' sign. Required if contactid is not provided. |
text | string | Yes | Note content. |
hidden | boolean | No | If true, the note does not mark the conversation as pending. |
tagId | string | No | ID of a tag to assign to the contact along with the note. |
Example request
curl -X POST https://api.manycontacts.com/v1/message/note \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "number": "34600111222", "text": "Cliente VIP, priorizar respuesta", "hidden": true }'
Example response
{
"id": "3b1e...",
"type": 2,
"contact_id": "8f3c...",
"timestamp": "2026-07-09T13:00:00.000Z",
"text": "Cliente VIP, priorizar respuesta"
}
POST /v1/message/interactive
Sends an interactive message with quick-reply buttons or a list of options. Based on the number of buttons, ManyContacts automatically picks the right format.
| Parameter | Type | Required | Description |
text | string | Yes | Message body. |
buttons | string[] | Yes | List of button titles (1 to 10). With 1-3 buttons, reply buttons are sent (max 20 chars); with 4-10, a list is generated (max 24 chars). |
number | string | Conditional | Contact phone in international format, without the '+' sign. Required if contactid is not provided. |
contactid | string | Conditional | Contact ID (UUID). Alternative to number. |
header | string | No | Optional message header (max 60 chars). |
footer | string | No | Optional message footer (max 60 chars). |
cta | string | No | Text of the button that opens the list (list mode only, max 20 chars). Defaults to 'View options'. |
Requires the organization to use WhatsApp API or WhatsApp Coexistence (Meta gateway) and the contact to have messaged within the last 24 hours (Meta service window).
Example request
curl -X POST https://api.manycontacts.com/v1/message/interactive \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"number": "34600111222",
"text": "¿Confirmas tu cita?",
"header": "Recordatorio",
"footer": "Clínica ManyContacts",
"buttons": ["Sí, confirmo", "Reprogramar", "Cancelar"]
}'
Example response
{ "id": "8f3c...", "error": null }
Specific errors
| Code | error | Meaning |
400 | invalid_parameters | Missing parameters or failed validations (empty text, button count out of range, exceeded lengths...). |
404 | contact_not_found | No contact exists with that number or ID. |
422 | gateway_not_supported | The organization does not have WhatsApp API or Coexistence enabled. |
422 | outside_24h_window | The contact is outside Meta's 24-hour window. Use a template to reopen the conversation. |
Contacts (v1)
Manage your contacts by ID (UUID). Most actions that take a number auto-create the contact if it doesn't exist.
Note: endpoints that take a number auto-create the contact (source: 'api') if it doesn't exist.
Endpoints that return a contact use this shape (main fields):
{
"id": "8f3c...",
"name": "Juan",
"email": null,
"open": true,
"last_user_id": null,
"number": "34600111222",
"notes": null,
"locked": false,
"customFields": {},
"tags": [{ "id": "a1b2...", "name": "Cliente", "color": "#55efc4" }]
}
GET /v1/contacts
List of contacts with filters (assignment, page, closed, users, tags).
| Parameter | Type | Required | Description |
filter | integer (query) | No | 0 = only unassigned and open chats; 1 = all chats. |
page | integer (query) | No | Results page (50 per page, starting at 0). |
closed | boolean (query) | No | If 'true', returns only closed conversations. |
users | string[] (query) | No | Filter by assigned user IDs (repeatable parameter). |
tags | string[] (query) | No | Filter by tag IDs; the contact must have all of them (repeatable parameter). |
Example request
curl "https://api.manycontacts.com/v1/contacts?filter=1&page=0&closed=false" \
-H "apikey: TU_API_KEY"
Example response
[
{
"id": "8f3c...",
"name": "Juan",
"email": null,
"open": true,
"last_user_id": null,
"number": "34600111222",
"notes": null,
"locked": false,
"customFields": {},
"tags": []
}
]
GET /v1/contact/:id
Get a contact by its ID.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl https://api.manycontacts.com/v1/contact/8f3c... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": true, "tags": [] }
GET /v1/contact/phone/:phone
Get a contact by phone number.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
If no contact exists with that number, it returns an empty object { }.
Example request
curl https://api.manycontacts.com/v1/contact/phone/34600111222 \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": true, "tags": [] }
POST /v1/contact
Create a contact (or return the existing one). Requires number.
| Parameter | Type | Required | Description |
number | string | Yes | Contact phone in international format, without the '+' sign. Required if contactid is not provided. |
name | string | No | Contact name. |
assigned | string | No | ID of the user to assign the contact to on creation. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "number": "34600111222", "name": "Juan" }'
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": true, "tags": [] }
PUT /v1/contact/:id
Update contact fields: name, number, open, notes, email, locked.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
name | string | No | Contact name. |
number | string | No | New phone number for the contact. |
open | boolean | No | Conversation state (true = open). |
notes | string | No | Contact notes. |
email | string | No | Contact email. |
locked | boolean | No | Whether the contact is locked. |
Example request
curl -X PUT https://api.manycontacts.com/v1/contact/8f3c... \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Juan Pérez", "email": "juan@example.com" }'
Example response
HTTP/1.1 200 OK
Returns 200 with no body when the operation succeeds.
PUT /v1/contact/:id/customField
Create or update a custom field (key + value).
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
key | string | Yes | Custom field name. |
value | string | Yes | Custom field value. |
Example request
curl -X PUT https://api.manycontacts.com/v1/contact/8f3c.../customField \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "key": "dni", "value": "12345678Z" }'
Example response
HTTP/1.1 200 OK
Returns 200 with no body when the operation succeeds.
POST /v1/contact/:id/assign/:userId
Assign the contact to a user.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
userId | string (path) | Yes | ID of the user (agent) to assign the contact to. |
If the user is an AI agent and the organization has no AI credits, it returns 402 with { "error": "no_ai_credits" }.
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../assign/5d2a... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "last_user_id": "5d2a...", "open": true, "tags": [] }
POST /v1/contact/:id/unassign
Remove the contact's assignment.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../unassign \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "last_user_id": null, "open": true, "tags": [] }
POST /v1/contact/:id/close
Close the contact's conversation.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../close \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": false, "tags": [] }
POST /v1/contact/:id/open
Open the contact's conversation.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../open \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": true, "tags": [] }
POST /v1/contact/:id/tag/:tagId
Add a tag to the contact.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
tagId | string (path) | Yes | Tag ID. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../tag/a1b2... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [{ "id": "a1b2...", "name": "Cliente", "color": "#55efc4" }] }
DELETE /v1/contact/:id/tag/:tagId
Remove a tag from the contact.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
tagId | string (path) | Yes | Tag ID. |
Example request
curl -X DELETE https://api.manycontacts.com/v1/contact/8f3c.../tag/a1b2... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
POST /v1/contact/:id/team/:teamId
Assign the contact to a team.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
teamId | string (path) | Yes | Team ID. |
Example request
curl -X POST https://api.manycontacts.com/v1/contact/8f3c.../team/7c9d... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
DELETE /v1/contact/:id/team/:teamId
Remove the contact from a team.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
teamId | string (path) | Yes | Team ID. |
Example request
curl -X DELETE https://api.manycontacts.com/v1/contact/8f3c.../team/7c9d... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
GET /v1/contact/:id/mediafiles/list
List the contact's media files (excludes audio).
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl https://api.manycontacts.com/v1/contact/8f3c.../mediafiles/list \
-H "apikey: TU_API_KEY"
Example response
[
{
"id": "e5f6...",
"filename": "factura.pdf",
"mimetype": "application/pdf",
"createdAt": "2026-07-09T13:00:00.000Z",
"url": "https://app.manycontacts.com/api/message/8f3c.../media/e5f6..."
}
]
GET /v1/contact/:id/bot/init
Trigger the chatbot's first message to the contact.
| Parameter | Type | Required | Description |
id | string (path) | Yes | Contact ID (UUID), in the path. |
Example request
curl https://api.manycontacts.com/v1/contact/8f3c.../bot/init \
-H "apikey: TU_API_KEY"
Example response
HTTP/1.1 200 OK
Returns 200 with no body when the operation succeeds.
Contacts (v2)
The v2 API identifies the contact directly by phone number in the path, instead of by ID. It includes the same assignment, tags, teams, open/close and custom-field endpoints as v1, plus these specific ones:
GET /v2/contact/:phone
Get the contact (includes internal notes) by phone.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl https://api.manycontacts.com/v2/contact/34600111222 \
-H "apikey: TU_API_KEY"
Example response
{
"id": "8f3c...",
"name": "Juan",
"number": "34600111222",
"open": true,
"tags": [],
"internal_notes": [
{ "text": "Cliente VIP", "createdAt": "2026-07-09T13:00:00.000Z" }
]
}
PUT /v2/contact/:phone
Create or update the contact by phone.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
name | string | No | Contact name. |
open | boolean | No | Conversation state (true = open). |
notes | string | No | Contact notes. |
email | string | No | Contact email. |
locked | boolean | No | Whether the contact is locked. |
Example request
curl -X PUT https://api.manycontacts.com/v2/contact/34600111222 \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Juan Pérez", "email": "juan@example.com" }'
Example response
{ "id": "8f3c...", "name": "Juan Pérez", "number": "34600111222", "email": "juan@example.com", "open": true, "tags": [] }
PUT /v2/contact/:phone/customField
Create or update a custom field (creates the contact if it doesn't exist).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
key | string | Yes | Custom field name. |
value | string | Yes | Custom field value. |
Example request
curl -X PUT https://api.manycontacts.com/v2/contact/34600111222/customField \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "key": "dni", "value": "12345678Z" }'
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "customFields": { "dni": "12345678Z" }, "tags": [] }
POST /v2/contact/:phone/assign/:userId
Assign the contact (by phone) to a user.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
userId | string (path) | Yes | ID of the user (agent) to assign the contact to. |
If the user is an AI agent and the organization has no AI credits, it returns 402 with { "error": "no_ai_credits" }.
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/assign/5d2a... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "last_user_id": "5d2a...", "open": true, "tags": [] }
POST /v2/contact/:phone/unassign
Remove the contact's assignment (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/unassign \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "last_user_id": null, "open": true, "tags": [] }
POST /v2/contact/:phone/close
Close the contact's conversation (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/close \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": false, "tags": [] }
POST /v2/contact/:phone/open
Open the contact's conversation (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/open \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "open": true, "tags": [] }
POST /v2/contact/:phone/tag/:tagId
Add a tag to the contact (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
tagId | string (path) | Yes | Tag ID. |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/tag/a1b2... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [{ "id": "a1b2...", "name": "Cliente", "color": "#55efc4" }] }
POST /v2/contact/:phone/tag/name/:tagName
Add a tag by name (creates tag and contact if they don't exist).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
tagName | string (path) | Yes | Tag name (created if it doesn't exist). |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/tag/name/Cliente \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [{ "id": "a1b2...", "name": "Cliente", "color": "#55efc4" }] }
DELETE /v2/contact/:phone/tag/:tagId
Remove a tag from the contact (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
tagId | string (path) | Yes | Tag ID. |
Example request
curl -X DELETE https://api.manycontacts.com/v2/contact/34600111222/tag/a1b2... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
POST /v2/contact/:phone/team/:teamId
Assign the contact (by phone) to a team.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
teamId | string (path) | Yes | Team ID. |
Example request
curl -X POST https://api.manycontacts.com/v2/contact/34600111222/team/7c9d... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
DELETE /v2/contact/:phone/team/:teamId
Remove the contact (by phone) from a team.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
teamId | string (path) | Yes | Team ID. |
Example request
curl -X DELETE https://api.manycontacts.com/v2/contact/34600111222/team/7c9d... \
-H "apikey: TU_API_KEY"
Example response
{ "id": "8f3c...", "name": "Juan", "number": "34600111222", "tags": [] }
GET /v2/contact/:phone/mediafiles/list
List the contact's media files (excludes audio).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl https://api.manycontacts.com/v2/contact/34600111222/mediafiles/list \
-H "apikey: TU_API_KEY"
Example response
[
{
"id": "e5f6...",
"filename": "factura.pdf",
"mimetype": "application/pdf",
"createdAt": "2026-07-09T13:00:00.000Z",
"url": "https://app.manycontacts.com/api/message/8f3c.../media/e5f6..."
}
]
GET /v2/contact/:phone/bot/init
Trigger the chatbot's first message to the contact (by phone).
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
Example request
curl https://api.manycontacts.com/v2/contact/34600111222/bot/init \
-H "apikey: TU_API_KEY"
Example response
HTTP/1.1 200 OK
Returns 200 with no body when the operation succeeds.
PUT /v2/contact/:phone/stage/:column
Move the contact to the funnel stage identified by its order.
| Parameter | Type | Required | Description |
phone | string (path) | Yes | Contact phone in international format (digits only), in the path. |
column | integer (path) | Yes | Order (index) of the default funnel stage, starting at 0. |
Example request
curl -X PUT https://api.manycontacts.com/v2/contact/34600111222/stage/2 \
-H "apikey: TU_API_KEY"
Example response
HTTP/1.1 200 OK
Returns 200 with no body when the operation succeeds.
Templates (v1)
Send Meta-approved WhatsApp templates. Useful to start conversations outside the 24-hour window. v1 supports a single body variable via the text parameter.
GET /v1/templates
List approved and visible templates.
This endpoint takes no parameters.
Example request
curl https://api.manycontacts.com/v1/templates \
-H "apikey: TU_API_KEY"
Example response
[
{
"name": "bienvenida",
"text": "Hola {{1}}, tu cita es el {{2}}",
"hasImage": false,
"hasDocument": false,
"hasVideo": false
}
]
POST /v1/template/:templateName/:number
Send a template to a number (body variable in text).
| Parameter | Type | Required | Description |
templateName | string (path) | Yes | Exact name of the Meta-approved template. |
number | string (path) | Yes | Destination phone in international format, in the path. |
text | string | No | Value for the template body variable. |
Example request
curl -X POST https://api.manycontacts.com/v1/template/bienvenida/34600111222 \
-H "apikey: TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "text": "Juan" }'
Example response
{ "id": "8f3c...", "error": null }
POST /v1/template/:templateName/:number/media
Send a template with a media attachment.
| Parameter | Type | Required | Description |
templateName | string (path) | Yes | Exact name of the Meta-approved template. |
number | string (path) | Yes | Destination phone in international format, in the path. |
file | file (multipart) | Yes | File to send (multipart/form-data). |
text | string | No | Value for the template body variable. |
Example request
curl -X POST https://api.manycontacts.com/v1/template/bienvenida/34600111222/media \
-H "apikey: TU_API_KEY" \
-F "text=Juan" \
-F "file=@catalogo.pdf"
Example response
{ "id": "8f3c...", "error": null }
Webhooks
ManyContacts can forward your organization's events to your own URL via POST requests, so you can integrate events into your systems in real time.
Configure them in the app: Settings → Developers. Enable forwarding and set an HTTPS destination URL.
Each event is sent as a POST with a JSON body in this shape (event, delta and the full contact object):
{
"event": "message_new",
"delta": {
"contactId": "8f3c...",
"message": { "id": "...", "text": "Hola", "type": "received", "metadata": { "time": "2026-07-09T13:00:00.000Z" } }
},
"contact": {
"id": "8f3c...",
"name": "Juan",
"email": null,
"open": true,
"last_user_id": null,
"number": "34600111222",
"notes": null,
"locked": false,
"customFields": {},
"tags": []
}
}
Available events
event | Description |
message_new | New inbound message from the contact. |
message_sent | Outbound message sent to the contact. |
mediafile_new | New media file received or sent. |
contact_created | A new contact has been created. |
contact_update | The contact has been updated (e.g. its notes). |
contact_update_custom_fields | The contact's custom fields have been updated. |
contact_update_tag_added | A tag has been added to the contact. |
contact_update_tag_deleted | A tag has been removed from the contact. |
contact_ai_welcome | The AI agent has sent a welcome message. |
conversation_data | Structured data extracted from the conversation by AI. |
message_flow_new | Response received from a Meta Flow. |
For safety, if your endpoint repeatedly returns errors, ManyContacts will automatically disable webhook forwarding.