Messaging

Contacts

Create, update and look up contacts, upsert them by channel identity to keep Gauge in step with your own system, and erase them.

Live

A contact is a person, merged across channels. Contacts are workspace-wide: a key with contact access sees every contact, the same list the console shows. Every contact endpoint needs a live key that is not pinned to an App.

EndpointScope
GET /v2/contactscontacts:readList and search contacts
POST /v2/contactscontacts:writeCreate a contact (201)
GET /v2/contacts/{id}contacts:readOne contact
PATCH /v2/contacts/{id}contacts:writeUpdate fields or custom fields
PUT /v2/contacts/by-identity/{channel}/{externalId}contacts:writeCreate (201) or update (200) by channel identity
GET, POST /v2/contacts/{id}/identitiescontacts:read, contacts:writeList or add a handle ({ "channel", "externalId" })
DELETE /v2/contacts/{id}/identities/{identityId}contacts:writeRemove a handle
POST /v2/contacts/{id}/tags, DELETE /v2/contacts/{id}/tags/{tag}contacts:writeAdd tags ({ "tags": [...] }), remove one
POST /v2/contacts/{id}/mergecontacts:writeMerge sourceId into this contact
DELETE /v2/contacts/{id}contacts:write + erasure rightErase the contact (irreversible)

The contact object

{
  "id": "2b9d4f61-7a3c-4e8b-9d0f-1a2b3c4d5e60",
  "displayName": "Layla Haddad",
  "email": "layla@example.com",
  "phone": "+447700900123",
  "title": null,
  "companyId": null,
  "companyName": null,
  "lifecycleStage": "customer",
  "isVip": false,
  "tags": ["vip"],
  "customFields": { "plan": "gold" },
  "identities": [
    { "id": "8c1d…", "channel": "whatsapp_cloud", "externalId": "447700900123", "connectionId": "9b2f6c1e-3d4a-4e5b-8f70-1a2b3c4d5e6f" },
    { "id": "9d2e…", "channel": "email", "externalId": "layla@example.com", "connectionId": null }
  ],
  "createdAt": "2026-10-20T16:02:11.903Z",
  "updatedAt": "2026-10-21T09:28:40.112Z"
}

GET /v2/contacts takes, all optional: q (name, email, phone or company contains), email, phone (any format, matched on digits), tag, company, updatedSince, createdSince, channel + externalId (the contact holding that handle), and sort (-createdAt, the default, createdAt, updatedAt or -updatedAt).

Create and update

POST /v2/contacts takes displayName, email, phone, country (for a national phone number: US, CA or GB), title, companyId or companyName (found or created), customFields and tags. It needs at least a displayName, an email or a phone. An email or phone another contact already holds answers 409 conflict.

PATCH /v2/contacts/{id} takes the same fields except email and tags (add handles and tags with their own endpoints).

Sync from your system: upsert by identity

The simplest way to keep Gauge in step with your CRM or database is to upsert each customer by something both systems know, such as their phone number on a WhatsApp connection or their email address:

curl -X PUT "https://app.gauge.chat/backend/v2/contacts/by-identity/whatsapp_cloud/+447700900123" \
  -H "Authorization: Bearer $GAUGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "displayName": "Layla Haddad", "customFields": { "plan": "gold" } }'

The body takes displayName, title, companyId or companyName, customFields and country. The handle in the path is normalized the way the inbox files it (a phone to E.164). If a contact holds that handle, it is updated and the answer is 200; otherwise a contact is created with that handle and the answer is 201. Run it as often as you like: the result is the same.

Erase a contact

DELETE /v2/contacts/{id} is the GDPR erasure: the contact's handles are deleted and their messages redacted. It cannot be undone. It needs contacts:write and the key's member must hold the erasure right (Owner or Admin); otherwise it answers 403. Pass an optional ?reason= for the audit log. The answer counts what was erased:

{ "id": "2b9d…", "erased": true, "erasedAt": "2026-10-21T10:00:00.000Z", "identitiesDeleted": 2, "messagesRedacted": 14 }

Events

Creating, renaming, merging and changing a contact's handles or fields raise contact.created and contact.updated webhooks, as in the console.

On this page