This endpoint allows you to create a new conversation between a contact and an account,
with the first message included. The conversation can be initiated by either party.
Use Cases
1. Contact initiates conversation (e.g., customer sends a support request)
When sender_type is "contact", the contact is the one sending the message.
- The conversation will be automatically assigned to an account/team based on your routing rules
- You only need to specify the
polymorphic_contact_id - The
account_idfield is not required and will be ignored if provided - AI chatflow may be triggered if configured
- You can optionally bypass routing rules and chatflows by specifying
assignee_typeandassignee_id
to assign the conversation directly to a specific account or team (see section below)
2. Account initiates conversation (e.g., team member proactively reaches out)
When sender_type is "account", the account is the one sending the message.
- You must specify both
polymorphic_contact_id(recipient) andaccount_id(sender) - The conversation will be assigned to the sender account by default
- You can optionally specify
assignee_typeandassignee_idto assign to a different account or team - No AI chatflow will be triggered
Request Fields
Required fields
polymorphic_contact_id(string): The contact identifier involved in the conversation. Can be:- Numeric Customerly Contact ID:
29911301 - Custom User ID (prefix
cuid:):cuid:user_123 - Custom Lead ID (prefix
clid:):clid:lead_456 - WhatsApp Number (prefix
wa:):wa:+1234567890 - User Email (prefix
uem:):uem:[email protected] - Lead Email (prefix
lem:):lem:[email protected]
- Numeric Customerly Contact ID:
sender_type(string): Who is sending the message - either"contact"or"account"- At least one of:
contentorattachmentsmust be provided
Conditional fields
account_id(integer): Required only whensender_typeis"account". The account sending the message.
Optional fields
content(string): Message text content. HTML is supported (safe tags only: p, br, b, i, u, a, img)channel(string): Communication channel. Options:"in_app"(default),"email"- Note: Email channel requires a verified custom domain
attachments(array): Array of file attachments (max 5 files, 5MB each)assignee_type(string): Type of the desired assignee. Options:"account","team". Must be provided
together withassignee_id. Whensender_typeis"contact", bypasses routing rules and chatflows.
Whensender_typeis"account", overrides the default assignment to the sender.assignee_id(integer): ID of the account or team to assign the conversation to. Must be provided
together withassignee_type.
Direct Assignment
You can optionally provide assignee_type and assignee_id to assign the conversation to a specific
account or team, regardless of sender_type.
- When
sender_typeis"contact": bypasses routing rules and chatflows entirely. - When
sender_typeis"account": overrides the default assignment (sender account); useful when
account A sends the message but the conversation should be handled by account B or a team. - Both fields must be provided together; providing only one results in a validation error.
Content & Attachments
HTML Content
- HTML is automatically sanitized for security
- Allowed tags:
<p>,<br>,<b>,<i>,<u>,<a>,<img> - All other tags and potentially dangerous content will be stripped
Attachments
- Maximum 5 attachments per message
- Maximum 5MB per file
- Format: Base64 encoded with data URI scheme
data:mime/type;base64,content - Image attachments are automatically embedded in the message content
- Non-image attachments are shown as downloadable files
Response
Returns the created conversation object with:
- Full conversation details
- First message information
- Assignment information
- Contact details
Examples
Example 1: Contact sends message (customer support request)
{
"polymorphic_contact_id": "123",
"sender_type": "contact",
"content": "<p>Hello, I need help with my order #12345</p>",
"channel": "in_app"
}→ Conversation created and automatically assigned based on routing rules
Example 2: Account proactively messages a contact
{
"polymorphic_contact_id": "123",
"account_id": 456,
"sender_type": "account",
"content": "<p>Hi! I noticed you haven't completed your order. Can I help?</p>",
"channel": "in_app"
}→ Conversation created and assigned to account 456
Example 3: Contact sends message with direct account assignment (bypasses routing rules)
{
"polymorphic_contact_id": "123",
"sender_type": "contact",
"content": "<p>Hello, I need help!</p>",
"assignee_type": "account",
"assignee_id": 456
}→ Conversation created and assigned directly to account 456, routing rules and chatflows skipped
Example 4: Contact sends message with direct team assignment
{
"polymorphic_contact_id": "123",
"sender_type": "contact",
"content": "<p>I need billing support</p>",
"assignee_type": "team",
"assignee_id": 789
}→ Conversation created and assigned directly to team 789, routing rules and chatflows skipped
Example 5: Message with attachments
{
"polymorphic_contact_id": "123",
"sender_type": "contact",
"content": "<p>Here's the screenshot of the error</p>",
"channel": "in_app",
"attachments": [
{
"filename": "error-screenshot.png",
"base64": "data:image/png;base64,iVBORw0KGgo..."
}
]
}→ Image will be embedded in the message content automatically
Example 6: Attachment only (no text content)
{
"polymorphic_contact_id": "123",
"sender_type": "contact",
"channel": "in_app",
"attachments": [
{
"filename": "document.pdf",
"base64": "data:application/pdf;base64,JVBERi0..."
}
]
}→ Conversation created with attachment only
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
401Authentication required
403Permission denied
404Contact or account not found
422Validation failed
500Internal server error