# ManyContacts API — Developer Documentation

Canonical: https://www.manycontacts.com/en/api/

Developers

# ManyContacts API

 Integrate WhatsApp into your applications: send messages, manage contacts and receive real-time events through webhooks. A simple REST API over HTTPS that returns JSON.

 Get your API key
 View OpenAPI spec

 Contents

- Authentication

- Rate limits

- Errors

-

 Messages

- POST /message/text

- POST /message/media

- POST /message/note

- POST /message/interactive

-

 Contacts (v1)

- GET /contacts

- GET /contact/:id

- GET /contact/phone/:phone

- POST /contact

- PUT /contact/:id

- PUT /contact/:id/customField

- POST /contact/:id/assign

- POST /contact/:id/unassign

- POST /contact/:id/close

- POST /contact/:id/open

- POST /contact/:id/tag/:tagId

- DEL /contact/:id/tag/:tagId

- POST /contact/:id/team/:teamId

- DEL /contact/:id/team/:teamId

- GET /contact/:id/bot/init

-

 Contacts (v2)

- GET /contact/:phone

- PUT /contact/:phone

- PUT /contact/:phone/customField

- POST /contact/:phone/assign

- POST /contact/:phone/unassign

- POST /contact/:phone/close

- POST /contact/:phone/open

- POST /contact/:phone/tag/:tagId

- POST /contact/:phone/tag/name/:tagName

- DEL /contact/:phone/tag/:tagId

- POST /contact/:phone/team/:teamId

- DEL /contact/:phone/team/:teamId

- GET /contact/:phone/bot/init

- PUT /contact/:phone/stage/:column

-

 Tags

- GET /tags

- POST /tag

- PUT /tag/:id

- DEL /tag/:id

-

 Teams

- GET /teams

-

 Templates (v1)

- GET /templates

- POST /template/:name/:number

- POST /template/:name/:number/media

-

 Templates (v2)

- POST /template/:name/:number

- POST /template/:name/:number/media

-

 Users

- GET /users

- Webhooks

## Authentication

 All calls are made over HTTPS against the API base URL. Responses are returned as JSON.

 Base URL: https://api.manycontacts.com
 Authentication uses an apikey HTTP header with your organization's key. Every request must include this header.

 curl https://api.manycontacts.com/v1/contacts \
 -H "apikey: TU_API_KEY"
 Find (and regenerate) your API key in the app: Settings → Developers. The key is not available during the trial period.

## Rate limits

 Requests are limited per organization within a 60-second window, based on your plan:

 | Plan| Limit|

 | Paid account| 60 req / min|

 | Free / trial account| 10 req / min|

 When you exceed the limit, the API responds with a 429 status. The TTL field shows the seconds left before you can retry.

 HTTP/1.1 429 Too Many Requests
{ "error": "Too many requests. Try again after sometime or contact support@manycontacts.com. TTL42" }

## Errors and status codes

 The API uses standard HTTP status codes. Newer endpoints also return a JSON body with an error field (and, when relevant, detail).

 | Code| Meaning|

 | 200| Success. The operation completed.|

 | 400| Bad request: missing or invalid parameters.|

 | 401| Unauthorized: the apikey header is missing or invalid.|

 | 402| Payment required: no AI credits available.|

 | 404| Not found: the requested resource does not exist.|

 | 422| Unprocessable: the operation isn't possible in the current state (e.g. unsupported gateway).|

 | 429| Too many requests: the rate limit has been exceeded.|

 | 500| Internal server error.|

 Older endpoints may return a status code without a JSON body. When the message is sent but the provider (Meta) returns a warning, the response is 200 with the detail inside the error field.

## 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. 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.|

 | 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/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/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.

## Tags

 Create and manage your organization's tags.

### GET /v1/tags

 List tags (optional name filter).

 | Parameter| Type| Required| Description|

 | filter| string (query)| No| Filter tags by name (partial, case-insensitive search).|

 Example request

 curl "https://api.manycontacts.com/v1/tags?filter=cliente" \
 -H "apikey: TU_API_KEY"
 Example response

 [
 { "id": "a1b2...", "name": "Cliente", "color": "#55efc4", "createdAt": "2026-07-09T13:00:00.000Z" }
]

### POST /v1/tag

 Create a tag (name required, color optional).

 | Parameter| Type| Required| Description|

 | name| string| Yes| Tag name.|

 | color| string| No| Color in hexadecimal format (max. 7 characters). If omitted, a random one is assigned.|

 Example request

 curl -X POST https://api.manycontacts.com/v1/tag \
 -H "apikey: TU_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{ "name": "VIP", "color": "#e84393" }'
 Example response

 { "id": "c3d4...", "name": "VIP", "color": "#e84393", "createdAt": "2026-07-09T13:00:00.000Z" }

### PUT /v1/tag/:id

 Update a tag's name or color.

 | Parameter| Type| Required| Description|

 | id| string (path)| Yes| Tag ID.|

 | name| string| No| Tag name.|

 | color| string| No| Color in hexadecimal format (max. 7 characters). If omitted, a random one is assigned.|

 Example request

 curl -X PUT https://api.manycontacts.com/v1/tag/c3d4... \
 -H "apikey: TU_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{ "name": "VIP Gold", "color": "#fdcb6e" }'
 Example response

 { "id": "c3d4...", "name": "VIP Gold", "color": "#fdcb6e", "createdAt": "2026-07-09T13:00:00.000Z" }

### DELETE /v1/tag/:id

 Delete a tag.

 | Parameter| Type| Required| Description|

 | id| string (path)| Yes| Tag ID.|

 Example request

 curl -X DELETE https://api.manycontacts.com/v1/tag/c3d4... \
 -H "apikey: TU_API_KEY"
 Example response

 HTTP/1.1 200 OK
 Returns 200 with no body when the operation succeeds.

## Teams

 List your organization's teams and their members.

### GET /v1/teams

 List teams with their members.

 This endpoint takes no parameters.

 Example request

 curl https://api.manycontacts.com/v1/teams \
 -H "apikey: TU_API_KEY"
 Example response

 [
 {
 "id": "7c9d...",
 "name": "Ventas",
 "members": [
 { "id": "5d2a...", "name": "Ana" },
 { "id": "6e3b...", "name": "Luis" }
 ]
 }
]

## 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 &#123;&#123;1&#125;&#125;, tu cita es el &#123;&#123;2&#125;&#125;",
 "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 }

## Templates (v2)

 Enhanced template sending: accepts header, body and button variables (dynamic URLs and copy-offer codes) as arrays (header_variables, variables and button_variables), with or without an attached media file.

### POST /v2/template/:templateName/:number

 Send a template with header, body and URL button variables (arrays).

 | 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.|

 | header_variables| string[]| No| Values for the template header variables (array).|

 | variables| string[]| No| Values for the template body variables (array).|

 | button_variables| string[]| No| Values for dynamic URL buttons and copy-offer buttons, in button order. A URL value is the suffix that replaces that button's variable. A copy-offer value is the coupon code (max 20 characters). Independent from body variables.|

 Example request

 curl -X POST https://api.manycontacts.com/v2/template/bienvenida/34600111222 \
 -H "apikey: TU_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{ "header_variables": ["ManyContacts"], "variables": ["Juan", "10:00"], "button_variables": ["verano", "BF26"] }'
 Example response

 { "id": "8f3c...", "error": null }

### POST /v2/template/:templateName/:number/media

 Send a v2 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).|

 | header_variables| string[]| No| Values for the template header variables (array).|

 | variables| string[]| No| Values for the template body variables (array).|

 | button_variables| string[]| No| Values for dynamic URL buttons and copy-offer buttons, in button order. A URL value is the suffix that replaces that button's variable. A copy-offer value is the coupon code (max 20 characters). Independent from body variables.|

 Example request

 curl -X POST https://api.manycontacts.com/v2/template/bienvenida/34600111222/media \
 -H "apikey: TU_API_KEY" \
 -F 'variables=["Juan", "10:00"]' \
 -F 'button_variables=["verano", "BF26"]' \
 -F "file=@catalogo.pdf"
 Example response

 { "id": "8f3c...", "error": null }

## Users

 List the users (agents) in your organization.

### GET /v1/users

 List users with their id, name and AI flag.

 This endpoint takes no parameters.

 Example request

 curl https://api.manycontacts.com/v1/users \
 -H "apikey: TU_API_KEY"
 Example response

 [
 { "id": "5d2a...", "name": "Ana", "ai": false },
 { "id": "9f8e...", "name": "Agente IA", "ai": true }
]

## 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.

## Ready to integrate?

 Get your API key in the app and start building. Questions? Get in touch.

 Start for free
 Contact support
