// Endpoints

Contacts

List, create, read and update contacts and their tags.

A contact is one phone number in your project. Each number appears only once: we match on the number, so +91 98765 43210 and +919876543210 are the same person.

GET/api/v1/contacts

List contacts

Scope: contacts:read

Newest first, paginated. Optional filters: search (name or phone) and tag (a tag id).

curl "https://whatsapp.esendblue.com/api/v1/contacts?search=priya&limit=20" \
  -H "Authorization: Bearer wacrm_live_YOUR_KEY"
POST/api/v1/contacts

Create (or find) a contact

Scope: contacts:write

Find or create by phone. A new contact returns 201; if the number already exists you get 200 with the existing contact, so it is safe to call on every sign-up in your own system.

FieldNotes
phoneRequired, E.164
nameOptional
emailOptional
companyOptional
tagsOptional array of tag names. Missing tags are created
curl -X POST https://whatsapp.esendblue.com/api/v1/contacts \
  -H "Authorization: Bearer wacrm_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+919876543210", "name": "Priya Sharma", "tags": ["website-signup"] }'
GET/api/v1/contacts/{id}

Read a contact

Scope: contacts:read

One contact. A contact from another project returns 404, not 403, so ids cannot be probed.

{ "data": {
    "id": "…",
    "phone": "+919876543210",
    "name": "Priya Sharma",
    "email": "priya@example.com",
    "company": "Sharma Traders",
    "avatar_url": null,
    "tags": [{ "id": "…", "name": "vip", "color": "#3b82f6" }],
    "created_at": "…",
    "updated_at": "…"
  } }
PATCH/api/v1/contacts/{id}

Update a contact

Scope: contacts:write

Updates only the fields you send: name, email, company, tags.

tags replaces, it does not add

Sending "tags": ["paid"] leaves the contact with exactly one tag. To add a tag, read the contact first and send the old tags plus the new one.
const API = "https://whatsapp.esendblue.com/api/v1";
const headers = {
  Authorization: `Bearer ${process.env.WHATSAPP_API_KEY}`,
  "Content-Type": "application/json",
};

const { data: contact } = await (await fetch(`${API}/contacts/${id}`, { headers })).json();
const tags = [...new Set([...contact.tags.map((t) => t.name), "paid"])];

await fetch(`${API}/contacts/${id}`, {
  method: "PATCH",
  headers,
  body: JSON.stringify({ tags }),
});