Skip to main content
The Customer CDP API is the single system-to-system surface for HueChat customers: contacts, unified profiles, audiences, preferences, membership and journeys. It uses the same validation, identity locks and event outbox as the dashboard, while every request remains restricted to the account that issued the API key.

Before you start

Create a scoped API key in HueChat → Account → Developer API with contacts:read for list, search and contact calls. Unified profiles, activity, timelines and advanced customer views also require deals:read because they contain deal and task data. Add contacts:write for create, update and merge. A merge also requires the key’s current owner to be an account administrator. The CDP routes under /cdp (customers, audiences, preferences, membership, access and journeys) use cdp:read and cdp:write. Keys that already hold contacts:* (or workflows:* for journeys) keep working.
Use the account id that issued the key. A key from another account receives 403; contact IDs, identifiers and merge aliases from other accounts are never resolved.

Create a contact

Use identifier for the stable customer ID from your ERP, CRM or commerce system. HueChat enforces its uniqueness inside one account.
Phone numbers are normalized to E.164. Email, identifier and phone conflicts are rejected instead of silently joining two people. Unknown JSON fields and oversized bodies are rejected. Contact creation and its contact.created event commit together.

Gender

gender is an optional, customer-supplied profile value. HueChat accepts only male, female or other (case-insensitive) and returns the canonical lower-case value, or an empty string when it has not been provided. It is never inferred from a name, conversation or appointment and must not be used for care, eligibility, advertising or attendance decisions. On create, omit the field when it is unknown. On update, omit it to preserve the current value or send "gender": "" to clear it. The value is retained in additional_attributes.gender for compatibility with older CDP clients; if both forms are sent, they must match.

First, middle and last name

A contact can also keep its name as first_name, middle_name (optional) and last_name. name stays the full display name.
  • Sending any part sets name to the parts that are set, joined by one space in the order first, middle, last. A name in the same request is ignored.
  • A part you omit, or send as null, keeps its stored value. "" clears it. If every part ends up empty, the parts are cleared and name is kept, or set to the name you sent.
  • On a contact without parts, the parts you omit are filled from its name: {"last_name": "Alotaibi"} on “Sara Mohammed” gives Sara, no middle name, and Alotaibi. A name without letters, such as a phone number, is never split.
  • Sending only name renames the contact and leaves the parts untouched. The name is never split into parts.
  • Each part, name, and the name the parts compose may have at most 255 characters. A longer value returns 422; a part that is not a string returns 400.
Contact create, update, get, list and search responses always include the three fields, each null when not set. They are also null after the contact is renamed with name alone, because the stored parts no longer compose name. Conversation list, detail and filter responses include them in meta.sender. The contact.created and contact.updated events of contact API creates, updates and merges carry them too; account webhooks deliver those events as contact_created and contact_updated.

Delivery address

additional_attributes.address is the customer’s delivery address: one object with these keys, each a single line of text.
Values are trimmed. country_code is a two-letter country code, stored in upper case. It is the delivery country, which can differ from the customer’s country of residence in additional_attributes.country_code. Sending address replaces the whole stored address; other attributes are merged as usual. Send "address": null, or an address whose fields are all empty, to clear it. HueChat rejects the request with 400 and saves nothing when the address has an unknown key, a value that is not single-line text, a value over its limit, an invalid country_code, or content without line1 and city:
When a payment link with a delivery address is created for the contact, HueChat saves that address here. A payment link requested with POST /api/v2/accounts/{accountId}/payments/requests (scope messages:write) needs the delivery country. When its delivery_address (the same keys as above) has line1 and city but no country_code, HueChat returns 422 before any payment provider is contacted, and saves nothing:
Payment links that AI agents and customer journeys send are not refused for a missing country. HueChat takes their country from the contact’s saved delivery address, then from the contact’s country of residence, and then, where one is known, from the merchant’s country. List with GET /api/v2/accounts/{accountId}/contacts. Use page, per_page (maximum 100) and sort. Add q, or call /contacts/search?q=…, to search name, email, normalized phone, identifier, company, website and domain. Sorting applies to ordinary lists and cannot be combined with q.
Search is fuzzy and ranked; use the returned numeric id for later calls.

Read and update

GET /contacts/{contactId} returns the editable record and its updated_at version. PATCH /contacts/{contactId} changes only supplied fields. Attribute objects are merged; an explicit empty email or phone clears that field. Provider-owned inbox identities are not retargeted by a profile update. The contact-only create/get surface neither accepts nor reveals inbox associations; use CDP profile routes for membership-filtered source context. If the requested ID was removed by a reviewed merge, HueChat resolves its account-local alias to the kept profile and returns merged_from_contact_id.

Merge duplicate customers

Read both records immediately before merging and send both updated_at values. Choose the kept record as base_contact_id and the duplicate as mergee_contact_id.
Each field choice is base or mergee. Supported keys are name, email, phone_number, identifier, company_name, location, city, country, country_code, notes, website and domain. The merge runs in one transaction and preserves conversations, consent evidence, labels, attachments, deals, appointments, journeys and memberships. It refuses stale versions, active delivery work and conflicting enrollments. Retrying the same completed merge returns the kept ID with replayed: true.

Read the unified CDP profile

Accounts with Customer CDP enabled and both contacts:read and deals:read can call:
  • GET /contacts/{contactId}/profile for the customer, sources, consent history, activity, deals, memberships, labels and first timeline page.
  • GET /contacts/{contactId}/timeline?cursor=… for cursor-paginated messages, events, deals and tasks.
Private-inbox rows remain filtered by the API key owner’s current membership. A disabled CDP plan returns 402 without weakening base contact access. The CDP customer list and profile records include the same top-level gender field while retaining additional_attributes.gender for compatibility. An administrator can call POST /contacts/{contactId}/consent with channel, purpose, status, human-readable evidence and the current expected_version. Evidence is bound to the contact’s current email or phone; it does not grant permission to a future address. A stale version returns 409. Revoking WhatsApp marketing consent also updates HueChat’s durable broadcast suppression.

Advanced Customer CDP API

The full CDP surface uses /api/v2/accounts/{accountId}/cdp. Every endpoint re-checks that the API key owner is still a member of the account. Feature-specific routes return 402 when Customer CDP, Audiences, Journeys or Membership is not enabled on the account plan.

Customer directory and configuration

Preference updates require an administrator. Use the simpler /contacts routes for ordinary synchronization and /cdp/customers when you need CDP views and aggregated customer summaries.

Audiences

Audiences require the Audiences plan feature. Dynamic audiences support up to 12 validated rules; static audiences support up to 5,000 accessible contact IDs. A static ID from another account or a private inbox the key owner cannot access is rejected. Create, update and delete require an administrator. Rule fields and operators are enumerated in the interactive API schema.

Customer journeys

Journeys require workflows:read or workflows:write plus the Journeys plan feature. Draft creation and preview do not send anything. Publishing activates future native-event enrollment and can cause real WhatsApp sends after HueChat re-checks consent, suppression, inbox access, the approved template and provider readiness. All journey mutations require workflows:write and an administrator.

Membership programs

Membership routes require the Membership plan feature. Reads use contacts:read; normal writes use contacts:write and an administrator. External commerce systems award points with POST /cdp/membership/members/{membershipId}/events. Give that integration a dedicated key with only membership:events; the key owner must still be a current administrator. provider + event_id is account-wide and idempotent, so a conflicting replay returns 409 instead of awarding points twice.
Keep separate least-privilege keys for contacts, journeys and membership events. HueChat hashes keys at rest, enforces expiry, optional IP allowlists and per-key rate limits, and rejects an account ID that does not own the key.

Deliberately not exposed

Hard delete and bulk delete are not part of this integration API. Customer history spans conversations, consent evidence and CDP activity; use HueChat’s authenticated privacy workflow when a record must be erased. The dashboard’s CDP onboarding-guide state is also intentionally not an integration endpoint. See the Contacts API reference for request fields and response schemas.