Contacts
Overview
Section titled “Overview”Contacts represent WhatsApp users you communicate with. Each contact stores their phone number, profile information, and conversation history.
List Contacts
Section titled “List Contacts”Retrieve a paginated list of contacts.
GET /api/contactsQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
limit | integer | Page size, 1–100. Default 50. |
search | string | Search by profile name (case-insensitive) or phone number. Truncated at 1000 characters. |
tags | string | Comma-separated tags; matches contacts having ANY of them |
Contacts are ordered by last_message_at DESC (nulls last), then created_at DESC.
Response
Section titled “Response”{ "status": "success", "data": { "contacts": [ { "id": "uuid", "phone_number": "1234567890", "name": "John", "profile_name": "John", "avatar_url": "https://...", "status": "active", "tags": ["vip", "billing"], "metadata": { "custom_field": "value" }, "last_message_at": "2024-01-01T12:00:00Z", "last_message_preview": "See you tomorrow!", "unread_count": 2, "assigned_user_id": "uuid", "whatsapp_account": "Main Business", "last_inbound_at": "2024-01-01T11:00:00Z", "service_window_open": true, "marketing_opt_out": false, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T12:00:00Z" } ], "total": 100, "page": 1, "limit": 50 }}Response Fields
Section titled “Response Fields”| Field | Type | Description |
|---|---|---|
whatsapp_account | string | The name of the WhatsApp account the contact belongs to (not a UUID) |
assigned_user_id | uuid | The agent the contact is assigned to, if any |
unread_count | integer | Number of unread incoming messages |
last_message_preview | string | Preview text of the most recent message |
service_window_open | boolean | True if the customer messaged within the last 24 hours (last_inbound_at) |
marketing_opt_out | boolean | Whether the contact has opted out of marketing messages |
status | string | Always the literal "active" — contacts have no status column. |
name | string | Mirrors profile_name; both hold the same value. |
Get Contact
Section titled “Get Contact”Retrieve a single contact by ID.
GET /api/contacts/{id}Response
Section titled “Response”{ "status": "success", "data": { "id": "uuid", "phone_number": "1234567890", "name": "John", "profile_name": "John", "avatar_url": "https://...", "status": "active", "tags": ["vip"], "assigned_user_id": "uuid", "whatsapp_account": "Main Business", "metadata": { "custom_field": "value" }, "unread_count": 0, "last_message_at": "2024-01-01T12:00:00Z", "last_message_preview": "Thanks!", "service_window_open": true, "marketing_opt_out": false, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T12:00:00Z" }}Create Contact
Section titled “Create Contact”Create a new contact (or restore a soft-deleted one with the same phone number). Requires contacts:write.
POST /api/contactsRequest Body
Section titled “Request Body”{ "phone_number": "+1234567890", "profile_name": "John Doe", "whatsapp_account": "Main Business", "tags": ["vip"], "metadata": { "custom_field": "value" }}| Field | Type | Required | Description |
|---|---|---|---|
phone_number | string | Yes | Contact phone number (a leading + is stripped) |
profile_name | string | No | Display name for the contact |
whatsapp_account | string | No | Name of the WhatsApp account to associate (not a UUID) |
tags | string[] | No | Tags to attach to the contact |
metadata | object | No | Freeform custom data |
Response
Section titled “Response”Returns the created contact in the same shape as Get Contact.
Update Contact
Section titled “Update Contact”Update an existing contact.
PUT /api/contacts/{id}Request Body
Section titled “Request Body”Only the fields you send are updated.
{ "profile_name": "John Smith", "whatsapp_account": "Main Business", "tags": ["vip", "billing"], "metadata": { "custom_field": "updated_value" }, "assigned_user_id": "uuid", "clear_assigned_agent": false}| Field | Type | Description |
|---|---|---|
profile_name | string | Display name |
whatsapp_account | string | Name of the associated WhatsApp account |
tags | string[] | Replaces the contact's tags |
metadata | object | Replaces the metadata object |
assigned_user_id | uuid | Assign the contact to an agent |
clear_assigned_agent | boolean | Set true to unassign the contact (takes precedence over assigned_user_id) |
Response
Section titled “Response”Returns the full updated contact (same shape as Get Contact).
Delete Contact
Section titled “Delete Contact”Delete a contact and all associated data.
DELETE /api/contacts/{id}Response
Section titled “Response”{ "status": "success", "data": null}Assign Contact
Section titled “Assign Contact”Assign a contact to a team member.
PUT /api/contacts/{id}/assignRequest Body
Section titled “Request Body”{ "user_id": "uuid"}To unassign a contact, set user_id to null:
{ "user_id": null}Response
Section titled “Response”{ "status": "success", "data": { "message": "Contact assigned successfully", "assigned_user_id": "uuid" }}Update Contact Tags
Section titled “Update Contact Tags”Replace the full set of tags on a contact. Requires contacts:write.
PUT /api/contacts/{id}/tagsRequest Body
Section titled “Request Body”{ "tags": ["vip", "billing"]}Response
Section titled “Response”{ "status": "success", "data": { "message": "Contact tags updated", "tags": ["vip", "billing"] }}Mark Contact Read
Section titled “Mark Contact Read”Mark all incoming messages from a contact as read (clears the unread badge). Used by the chat view when the conversation is open.
POST /api/contacts/{id}/mark-readResponse
Section titled “Response”{ "status": "success", "data": { "status": "ok" }}Contact Metadata
Section titled “Contact Metadata”The metadata field is a freeform JSON object that can hold any structured data. It is displayed in the Contact Info panel alongside tags and session data.
Supported Data Types
Section titled “Supported Data Types”Different value types are rendered differently in the panel:
| Type | Display |
|---|---|
| String, number | Key-value row |
| Boolean | Yes / No badge |
| Object | Collapsible section with key-value rows |
| Array of objects | Collapsible table with column headers |
| Array of primitives | Inline badges |
Example
Section titled “Example”{ "metadata": { "plan": "premium", "age": 30, "active": true, "address": { "city": "Mumbai", "state": "Maharashtra", "zip": "400001" }, "orders": [ { "id": "ORD-001", "amount": 1500, "status": "delivered" }, { "id": "ORD-002", "amount": 2300, "status": "pending" } ], "interests": ["fitness", "tech", "travel"] }}This renders as:
- General section —
plan,age, andactiveas key-value rows (boolean shown as a badge) - Address section — collapsible key-value pairs for
city,state,zip - Orders section — collapsible table with
Id,Amount,Statuscolumns - Interests section — inline badges:
fitness,tech,travel
Nesting Depth
Section titled “Nesting Depth”The panel supports one level of nesting. Top-level keys are organized as follows:
| Top-level value | Rendered as |
|---|---|
| Primitive (string, number, boolean) | Row in the General section |
| Object | Its own collapsible section with key-value rows |
| Array of objects | Its own collapsible section with a table |
| Array of primitives | Its own collapsible section with badges |
Values inside a nested object or array are always displayed as flat text. If a nested object contains another object, the inner value is shown as a raw JSON string. For example:
{ "metadata": { "address": { "city": "Mumbai", "location": { "lat": 19.07, "lng": 72.87 } } }}Here city displays as Mumbai, but location displays as {"lat":19.07,"lng":72.87}.
Get Session Data
Section titled “Get Session Data”Retrieve chatbot session data for a contact, including collected variables and panel configuration.
GET /api/contacts/{id}/session-dataResponse
Section titled “Response”{ "status": "success", "data": { "session_id": "uuid", "flow_id": "uuid", "flow_name": "Customer Support Flow", "session_data": { "customer_name": "John Doe", "customer_email": "john@example.com", "order_id": "ORD-12345", "order_status": "shipped" }, "panel_config": { "sections": [ { "id": "customer", "label": "Customer Info", "columns": 1, "collapsible": true, "default_collapsed": false, "order": 1, "fields": [ {"key": "customer_name", "label": "Name", "order": 1}, {"key": "customer_email", "label": "Email", "order": 2} ] }, { "id": "order", "label": "Order Details", "columns": 2, "collapsible": true, "default_collapsed": true, "order": 2, "fields": [ {"key": "order_id", "label": "Order ID", "order": 1}, {"key": "order_status", "label": "Status", "order": 2} ] } ] } }}Response Fields
Section titled “Response Fields”| Field | Type | Description |
|---|---|---|
session_id | uuid | The chatbot session ID |
flow_id | uuid | The flow that collected the data |
flow_name | string | Name of the flow |
session_data | object | Key-value pairs of collected variables |
panel_config | object | Panel display configuration from the flow |
Messaging & Notes
Section titled “Messaging & Notes”Contacts are the scope for conversation messages and internal notes.
Messages
Section titled “Messages”Messages are sent and retrieved under the contact resource. See the Messages API for full request/response details.
| Method | Path | Description |
|---|---|---|
GET | /api/contacts/{id}/messages | List messages for a contact (paginated) |
POST | /api/contacts/{id}/messages | Send a message to the contact |
POST | /api/contacts/{id}/messages/{message_id}/reaction | Add or remove an emoji reaction on a message |
Conversation Notes
Section titled “Conversation Notes”Internal, contact-scoped notes visible to agents (never sent to the customer). Requires chat:read to list and chat:write to modify.
| Method | Path | Description |
|---|---|---|
GET | /api/contacts/{id}/notes | List notes for a contact (cursor-paginated, oldest first) |
POST | /api/contacts/{id}/notes | Create a note |
PUT | /api/contacts/{id}/notes/{note_id} | Update a note |
DELETE | /api/contacts/{id}/notes/{note_id} | Delete a note |
Create Note Request Body
Section titled “Create Note Request Body”{ "content": "Customer prefers email follow-up."}Note Response
Section titled “Note Response”{ "status": "success", "data": { "id": "uuid", "contact_id": "uuid", "created_by_id": "uuid", "created_by_name": "Admin User", "content": "Customer prefers email follow-up.", "created_at": "2024-01-01T12:00:00Z", "updated_at": "2024-01-01T12:00:00Z" }}The list endpoint returns { "notes": [...], "total": <n>, "has_more": <bool> }.