The most up-to-date API documentation for Cloud Humans can be found at docs.cloudhumans.com/api-reference.** If there is any discrepancy between this article and the reference, the reference takes precedence.
When to use
-
When an external system (your backend, CRM, marketing automation) needs to initiate a conversation with a specific contact β without manual intervention by an agent.
-
For transactional and proactive notices per contact: order confirmation, payment reminder, status update, cart abandonment.
-
In two channels, with the same authentication (
api_access_token):-
WhatsApp β sends an approved template message to the contact's phone.
-
Authenticated Web Widget β displays a message that appears when the contact returns authenticated in the chat on your website/app.
-
Prerequisites
-
An API Access Token from Cloud Chat (available in your profile, under Profile β Settings β Access Token). It must be included in the header
api_access_token. -
The
account_idof your account (shown in the Cloud Chat URL). -
The address of your Cloud Chat instance, which is the domain shown in your browser when accessing the platform (e.g.,
cloudchat5.cloudhumans.com). Requests must be directed to this address. An address of another instance will respond with401. -
The token is valid only for the instance it was generated for. If you generate a new one, the previous one becomes invalid immediately, so update all systems using it.
-
For WhatsApp: a connected WhatsApp inbox + an approved template by Meta.
-
For Web Widget: a Web Widget inbox with HMAC authentication required (authenticated area / verified identity) + a identifiable contact.
How it works
Authentication
Both endpoints use the same header. Never expose the token on the frontend β these triggers are server-to-server.
api_access_token: YOUR_API_ACCESS_TOKEN
Content-Type: application/json
Send the token only in the api_access_token header, just the value, without quotes or the Bearer prefix. Do not add an Authorization header, as it will cause the request to be rejected with 401.
WhatsApp: template-based trigger
Sends (push) an active message β arrives on the contact's WhatsApp immediately. Since it's WhatsApp, the content must be an approved template.
POST https://{YOUR_DOMAIN}/api/v1/accounts/{ACCOUNT_ID}/conversations/create_proactive_whatsapp_conversation
{YOUR_DOMAIN} is your instance address (e.g., cloudchat5.cloudhumans.com).
{
"inbox_id": 123,
"phone_number": "+5511999998888",
"template_name": "payment_reminder",
"labels": ["campaign-x", "vip"],
"client": "John",
"amount": "R$ 120.00"
}
-
inbox_idβ the WhatsApp inbox through which the message is sent. -
phone_numberβ the contact's phone number in international format E.164 (with+and country code, e.g.,+5511999998888). -
template_nameβ name of the approved template. -
Template variables β each variable should be sent as a top-level field in the body (sibling to
inbox_id/phone_number/template_name), with the variable name of the template. Example: a template with variablesclientandamountshould receive the fields"client"and"amount". If the template uses numbered variables ({{1}},{{2}}), the fields are"1"and"2". Do not place these inside atemplate_paramsobject. -
labels(optional) β array of strings with tag titles to apply to the created conversation (e.g.,["campaign-x", "vip"]). Titles are normalized to lowercase, and tags are added without removing existing tags. New tags are automatically created in the account only if the token has admin or CX Engineer permissions; with an agent token, non-existent tags are ignored. Details at How to send proactive messages via WhatsApp API.
WhatsApp: request rate limit
The WhatsApp endpoint accepts up to 200 requests per minute per API key. Exceeding this results in a 429 response with the Retry-After header (seconds until retry). Wait this time before resending, and distribute large batches over multiple minutes. A request that receives 429 was not processed, so resending does not duplicate the message. Response body, other headers, and how the limit is counted are explained in What are the API request limits (rate limits) of Cloud Chat routes?.
Web Widget (authenticated area): contact-based trigger
Displays a passively appearing message: the widget does not push β the message shows up the next time the contact authenticates in the chat within the logged-in area. You can trigger this even for users who haven't opened the chat yet (by identifying via identifier).
POST https://{YOUR_DOMAIN}/api/v1/accounts/{ACCOUNT_ID}/conversations/create_proactive_web_widget_conversation
{
"inbox_id": 456,
"identifier": "user-42",
"content": "Hi John! I saw your plan expires tomorrow. Can I help you renew?",
"idempotency_key": "renewal-user-42-2026-06-28"
}
-
inbox_idβ the Web Widget inbox (HMAC required). -
Contact identification β send exactly one of these:
-
identifierβ your stable user ID. Creates the contact if it doesn't exist yet. -
emailβ uses an already identifiable contact with that email. -
contact_idβ the contact's ID in Cloud Chat.
-
-
contentβ free message text (no template required). -
idempotency_key(optional) β see below. -
contact_attributes(optional) β attributes/name to enrich the contact upon creation.
Delivery is passive: the message only becomes visible after the contact authenticates the session in the widget (HMAC). That's why this trigger is exclusive to logged-in areas.
Web Widget: identifier format
The identifier must be exactly the same value your app uses to generate the HMAC in the widget SDK for that user. If they differ (e.g., you send "42", but the widget sends "user-42"), Cloud Chat will treat them as different contacts and the message will not appear for the user.
-
identifierβ stable string (the same as in the HMAC). It's recommended to use the user's ID from your system. -
emailβ a valid email of an already identifiable contact.
Web Widget: multiple inboxes and contacts without phone
-
Multiple Web Widget inboxes. The
identifieridentifies the contact across the entire account, so the same user can be reached in different inboxes (e.g., different products or logged-in areas) using the sameidentifier. The trigger always occurs per inbox (inbox_id): each inbox maintains its own conversation/session with the contact. To talk to the user in two areas, send a message to eachinbox_id. -
When no phone number is present. Unlike WhatsApp (where number is the identity), in Web Widget the contact is identified by
identifier/emailand does not need a phone number. Contacts without a number are fully supported β the phone is irrelevant for this channel.
Idempotency (Web Widget)
Resends are safe if you use idempotency_key. The same key, within 24 hours, returns the same conversation, instead of creating a duplicate β useful for retry attempts. Reusing the same key for a different contact is rejected (idempotency_key_contact_mismatch).
Main errors
| Code | Meaning |
|---|---|
inbox_id_required / inbox_not_found |
Missing or not found inbox in the account. |
contact_not_identifiable |
Provided email/contact_id does not match an identifiable contact. |
ambiguous_contact_match |
The data matches more than one contact β refine identification. |
invalid_contact_attributes |
contact_attributes invalid for creating the contact. |
idempotency_key_contact_mismatch |
The idempotency_key has already been used for another contact. |
Remarks
-
WhatsApp = active (push, via template); Web Widget = passive (free text, upon next authentication). Choose the channel based on the desired delivery type.
-
The trigger is per contact in both channels (one-to-one), not a mass campaign.
-
The created conversation is out of the agents' queue/SLA until the contact engages β it does not count as active atendimento until someone responds.
-
Keep the
api_access_tokenonly on the server.