A contact is one person in one contact list: a WhatsApp phone number plus the details you keep about them (for example a first name), and optional tags. This section lets you add contacts, find them, change them and delete them.You need a contact list first. If you do not have one, read Getting started with contact lists.| What you want to do | Endpoint |
|---|
| Find contacts in a list | POST /contact |
| Add one or many contacts | POST /contact/create-contact |
| Change a contact | PUT /contact |
| Delete contacts | PUT /contact/delete-contact |
POST /contact is a "get" even though it uses POST: the filters go in the body.
1. The big picture#
Contact list
├─ Fields (Phone Number, Country Code, First Name, ... plus your own)
└─ Contacts
├─ one value per field (contact_data)
└─ tags (contact_tag_assignment)
Every value you save for a contact belongs to a field. To save a value you send the field's ID and the value, so you first need to know the field IDs of your list.
| What you need | Where to find it |
|---|
contact_list_id of an active list | Get Contact List (GET /contact/list) |
| The field IDs of that list | Get contact fields (GET /contact/field?contact_list_id=12) |
| Tag IDs (optional) | Get contact tags (GET /contact/tag?contact_list_id=12) |
The country code to use (for example IN) | Get country codes (GET /global/country-code) |
Three fields matter most:| Field name | Required | What to send |
|---|
| Phone Number | Always | The number without the country code, for example 9876543210. |
| Country Code | Always | The country's short code, for example IN, not +91. Use a value from Get country codes. |
| First Name | If your list has a First Name field | A non-empty name. |
Find the ID of each field by its name in the Get contact fields response. The IDs in the examples below (101, 102, 103) are samples; yours will differ.How the phone number is checked. Chronox checks that the number is a valid mobile number for the country you give, then stores it with the country code and digits only, for example 919876543210. A number that does not match the country, or a landline, is refused.
POST /contact/create-contactYou can add one contact or many in one request. Both use the same address.{
"contact_list_id": 12,
"contact_data": [
{ "contact_field_id": 101, "contact_data_value": "John" },
{ "contact_field_id": 102, "contact_data_value": "9876543210" },
{ "contact_field_id": 103, "contact_data_value": "IN" }
],
"contact_tag_id": [5, 6]
}
contact_tag_id is optional. Every tag must be one of this list's tags or a built-in tag (see Get contact tags); otherwise the whole request is refused.You get the saved contact back, inside its list:{
"status": true,
"data": [
{
"contact_list_id": 12,
"contact_list_name": "October customers",
"contact_list_status_id": 1,
"contact_list_status_name": "Active",
"flag_allow_duplicate_contact": false,
"contact": [
{
"contact_id": 5001,
"contact_phone_number": "919876543210",
"created_at_timestamp": "2026-01-01T00:00:00.000Z",
"updated_at_timestamp": null,
"flag_recent": false,
"flag_deleted": false,
"contact_tag_assignment": [
{
"contact_tag_assignment_id": 9001,
"contact_tag_id": 5,
"contact_tag_name": "VIP",
"created_at_timestamp": "2026-01-01T00:00:00.000Z",
"updated_at_timestamp": null
}
],
"contact_chatbot_assignment_data": [],
"contact_data": [
{
"contact_data_id": 7001,
"contact_field_id": 101,
"contact_field_name": "First Name",
"flag_default": true,
"contact_data_value_flag_json": false,
"contact_data_value": "John",
"created_at_timestamp": "2026-01-01T00:00:00.000Z",
"updated_at_timestamp": null
}
]
}
]
}
]
}
Keep contact_id (to change or delete the contact) and the contact_data_id values (to change a single value).Put the contacts in a contacts array. Tags can be set for everyone at the top level, or for one contact inside its own item.{
"contact_list_id": 12,
"contact_tag_id": [5],
"contacts": [
{
"contact_data": [
{ "contact_field_id": 101, "contact_data_value": "John" },
{ "contact_field_id": 102, "contact_data_value": "9876543210" },
{ "contact_field_id": 103, "contact_data_value": "IN" }
]
},
{
"contact_data": [
{ "contact_field_id": 101, "contact_data_value": "Asha" },
{ "contact_field_id": 102, "contact_data_value": "9123456789" },
{ "contact_field_id": 103, "contact_data_value": "IN" }
],
"contact_tag_id": [6]
}
]
}
A bulk request is partly successful: good contacts are created, bad ones are skipped and explained one by one. The index is the position of the contact in your contacts array, starting at 0.{
"status": true,
"total_contacts": 2,
"created_contacts": 1,
"failed_contacts": 1,
"results": [
{ "index": 0, "status": true, "contact_id": 5001 },
{ "index": 1, "status": false, "error": "Invalid phone number" }
],
"data": [ { "contact_list_id": 12, "contact_list_name": "October customers", "contact": [ ] } ]
}
data lists only the contacts that were created. Always check results (or failed_contacts) rather than just status.Reasons a single contact in a bulk request can fail:Message in results | What to do |
|---|
contact_data is required | Send at least one value. |
Phone number is required | Send the Phone Number field with a value. |
Country code is missing or invalid | Send the Country Code field with a value from Get country codes. |
First name is required | Send a non-empty First Name. |
Invalid contact_field_id | The field ID does not belong to this list. Check Get contact fields. |
Invalid contact_tag_id | The tag is not one of this list's tags or a built-in tag. Check Get contact tags. |
Invalid phone number | Not a valid mobile number for that country. |
Duplicate phone number in request | The same number appears twice in your request (and the list does not allow duplicates). |
Contact already exists | The number is already in the list (and the list does not allow duplicates). |
Send big imports in batches (for example a few hundred contacts per request) so each response stays small and easy to check.
Only contact_list_id is required. With nothing else, you get every contact in the list.{
"contact_list_id": 12,
"contact_id": 5001,
"contact_tag_id": [5, 6],
"contact_data": [
{
"contact_field_id": 101,
"contact_field_value": [
{ "contact_data_value": "John" }
]
}
]
}
| Field | What it does |
|---|
contact_list_id | Required. The list to look in. |
contact_id | Return only this contact. |
contact_tag_id | Return contacts that have at least one of these tags. |
contact_data | Return contacts whose value for a field matches. Capital letters do not matter. A contact must match every field you list. For one field you can list several values; matching any of them is enough. |
The response has the same shape as section 3 (a list with its contact array). A list with no matching contacts returns "contact": [].Each contact has flag_deleted. Ignore any contact where it is true.
{
"contact_id": 5001,
"contact_data": [
{ "contact_data_id": 7001, "contact_data_value": "Johnny" },
{ "contact_field_id": 104, "contact_data_value": "Delhi" }
],
"contact_tag_id": [5, 6]
}
Rules that are easy to get wrong:To change an existing value, send its contact_data_id (from Find contacts) and the new contact_data_value. Do not also send contact_field_id in the same item.
To add a value for a field the contact does not have yet, send contact_field_id and the value, without contact_data_id. Do not use this for a field that already has a value.
contact_tag_id is the complete list of tags the contact should have. Tags that are missing from your list are removed. If you leave contact_tag_id out, all tags are removed. Always send the full list.
The phone number cannot be changed. Trying to send a different number gives error 9315. Delete the contact and add a new one instead.
The Opt-out Meta tag is set by WhatsApp and cannot be added or removed by you (error 9314).
The contact's list must be active. A contact in an archived list cannot be changed (error 9330).
You get the updated contact back, in the same shape as section 3.
PUT /contact/delete-contactThis is a PUT with a body, not a DELETE.{ "contact_id": [5001, 5002] }
contact_id is a list, so you can delete several at once. If any ID is not found in your organization, nothing is deleted and you get error 9001.{
"status": true,
"data": {
"code": 9064,
"message": "Contact - '919876543210,919123456789' deleted successfully."
}
}
You cannot delete contacts from the Master Contact List (error 9309) or from an archived list (error 9330).Deleting a contact also removes its tags and values. A contact assigned to a chatbot is unassigned first. This cannot be undone from the API.
7. Common errors#
Errors come back with HTTP status 200 and "status": false. See Errors for the general format.| Code | What it means | What to do |
|---|
9001 | The body is wrong: missing list or contact ID, no Phone Number or Country Code, invalid country code or phone number, unknown field or tag, or a contact ID that is not yours. | Check every ID against the lookups in section 2. |
9270 | Contact already exists in this list (single add). | Update the existing contact instead, or allow duplicates on the list. |
9314 | The Opt-out Meta tag cannot be added or removed by you. | Leave that tag out. |
9315 | The phone number cannot be changed. | Delete the contact and add a new one. |
9309 | Contacts in the Master Contact List cannot be deleted. | Nothing to do. |
9330 | The list is archived, so the action is not allowed. | Make the list active first. |
9002 | The list ID is wrong or not yours (find). | Check contact_list_id. |
8. Quick checklist#
What this section doesn't cover#
Creating and managing the lists themselves: see Getting started with contact lists.
Creating tags and custom fields: see the Tags and fields folder.
Sending messages to your contacts: see Getting started with campaigns.