Skip to main content

Create a conversation

Use this endpoint when a customer submits a form or when a trusted backend needs to add a customer message to CXP:
intakeChannel, contact.email, and message.text are required. A successful response is 201 Created when CXP creates a conversation or 200 OK when Simple mode appends the message to an existing conversation.

Send the minimal request

intakeChannel must be an active tenant service-email address with an active AI Assistant. CXP uses the channel and contact identity with the same canonical conversation-resolution flow used for inbound email. If no matching contact exists, CXP creates one. If a contact exists, CXP adds the message to the newest non-Closed conversation in Simple mode or creates a new conversation in Advanced mode. If you omit conversation.subject and the resolved conversation has no subject, CXP sets Message from {contact.email}. In the minimal request above, the subject is Message from jane@example.com. An existing conversation subject is never replaced by this fallback.

Map a website contact form

This example maps name, phone, email, company, subject, product, and question fields. intakeChannel is an active service email configured in your tenant.
The mapping is: The custom field must already be configured for the tenant and must accept the provided value. CXP validates it before intake, then applies it through the standard Conversation custom-field update after the Contact, Conversation, and customer message are durable.

Contact and organization resolution

CXP resolves a contact using the supplied contact ID, email, and phone evidence. Those values must identify one compatible tenant contact; ambiguous or conflicting evidence returns 409 ContactIdentityConflict. The reserved anonymous Contact ID cannot be supplied. A non-empty phone value must be valid; CXP normalizes it to E.164 or returns 400 BadRequest instead of discarding it. When a contact exists, every supplied contact value is authoritative:
  • A different supplied email, phone, name, first name, or last name replaces the current value.
  • A value that already matches causes no write.
  • An omitted optional value remains unchanged.
Use contact.firstName and contact.lastName for the standard structured Contact properties. If you provide both without contact.name, CXP also sets the Contact display name to {firstName} {lastName}. An explicit contact.name takes precedence:
If no contact matches, CXP creates it. You do not need a create-or-update flag. For an organization, you may provide organizationId, name, or both. CXP uses the ID when it resolves to a tenant organization; otherwise it resolves an exact normalized name and creates the organization when no exact match exists. CXP associates the resolved organization with both the contact and the conversation. It does not use fuzzy matching or rename an organization implicitly.

Assign the resolved conversation

You can request an agent or team assignment after CXP resolves or creates the conversation. intakeChannel remains required even when you provide an assignee. To assign it to a team by exact name:
Use type: "agent" or type: "team", then provide exactly one of id or name. A name must match one active eligible agent or team exactly after normalization. Prefer id when you have it because it provides the most direct and lowest-latency lookup. Assignment and Assistant processing follow these rules:
  1. If the request contains conversation.assignee, CXP applies it only when the resolved conversation has no assignee. An existing assignee is never replaced.
  2. Supplying an assignee always prevents an AI Assistant turn for that request, even when CXP preserves an existing assignee instead of applying the requested one.
  3. If the request omits an assignee and the resolved conversation is AI-handled and unassigned, CXP starts an asynchronous turn using the AI Assistant configured for intakeChannel.
  4. If the resolved conversation is assigned to an agent or team, CXP sends the normal addressed customer-message notification to that existing or newly applied owner and does not start an Assistant turn.
  5. For a directly assigned agent, CXP also schedules the normal internal Agent Assist lifecycle when Agent Assist is configured. This is separate from the customer-facing AI Assistant turn and does not delay the API response.
Owner notifications and Agent Assist startup are asynchronous post-commit work. A successful response confirms that the conversation and customer message are durable; it does not wait for realtime notification delivery. An invalid or inactive intakeChannel, or a channel without an active AI Assistant, returns an error. There is no All Agents fallback.

Understand Simple-mode append behavior

In Simple mode, canonical resolution selects the contact’s newest non-Closed conversation and CXP then applies the request updates and adds the customer message.
  • If the conversation is assigned to an agent or team, CXP sends the normal addressed customer-message notification to that owner. A requested assignee cannot replace it. A directly assigned agent also retains the normal internal Agent Assist lifecycle when configured.
  • If the conversation has no assignee, a requested assignee is applied and no AI Assistant turn starts.
  • If the request has no assignee and an AI Assistant handles the unassigned conversation, CXP starts a turn using the Assistant configured for the required intakeChannel after the new message is durable.
  • If the existing status is Pending or Resolved, CXP reopens it to Open. A Closed conversation is not reused.
For a new conversation, canonical resolution first performs the normal Assistant conversation initialization, including the durable internal context required by the Assistant. CXP then stores the API-created customer message as a public user email message with messageSource: "public_api". intakeChannel is resolution and processing context; it is not a property of the conversation or customer message. The same subject rule applies when Simple mode resolves an existing subjectless conversation: a supplied subject wins; otherwise CXP sets Message from {contact.email}. A non-empty existing subject remains intact.

Understand asynchronous Assistant email

When the request omits an assignee and the resolved conversation is AI-handled and unassigned, the success response returns as soon as the contact, conversation, and customer message are durable. It does not wait for the Assistant’s answer. The Assistant processes the durable customer message asynchronously. If it answers by email, CXP sends a new email from the effective service address to the contact and creates the real email thread from that outbound message. The API intake itself does not fabricate an inbound email thread.

Read the success response

conversation.result is created or appended. contact.result is:
  • created: CXP created the contact.
  • updated: at least one supplied contact value changed.
  • matched: all supplied values already matched, so no contact write was needed.
conversation.assignee is null for an AI-handled, unassigned conversation. Otherwise it reports the preserved or newly applied agent or team. The response does not include the customer message ID/body, Assistant identity, notification status, Assistant turn status, Agent Assist lifecycle status, or email delivery status.

Handle a custom-field warning

If the Conversation and customer message are created or appended successfully but the separate custom-field update fails, CXP still returns 200 OK or 201 Created. The response includes:
The Contact, Conversation, and customer message remain successful. CXP also starts any eligible asynchronous Assistant turn. Record or alert on the warning so the custom-field configuration or persistence failure can be investigated; do not retry the entire Create Conversation request solely to repair custom fields, because every retry creates new intake work.

Handle errors and retries

Common endpoint errors include:
The endpoint has no request-idempotency header or duplicate suppression. Repeated successful calls add repeated effects. A tracing request ID does not change this behavior.
For all fields, limits, examples, and response schemas, open API reference in the developer navigation.