> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cxp.crescendo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create or continue a conversation

> Use the required intake email channel and its configured AI Assistant to run canonical conversation resolution, then update the resolved contact, organization, and conversation and append the customer message. In Simple mode this can append to the contact's existing non-closed conversation; in Advanced mode each API request starts a new intake thread. If the request omits a subject and the resolved conversation has none, CXP sets `Message from {contact.email}`. A supplied assignee is applied only when the resolved conversation is unassigned and always suppresses a customer-facing Assistant turn for this request. A directly assigned agent may separately receive the normal internal Agent Assist lifecycle when configured. Without a supplied assignee, CXP starts an asynchronous turn only when the resolved conversation is AI-handled and unassigned. Requested custom fields use a separate post-intake update. If that update fails, CXP still returns success with a `CustomFieldsUpdateFailed` warning and starts any eligible Assistant turn. Success confirms durable intake only. It does not wait for notification delivery, an AI Assistant turn, Agent Assist lifecycle work, or outbound email delivery. The JSON request body must not exceed 1 MiB. Every accepted POST executes; repeating a request can create or append another message.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /api/v1/cxm/tenants/{tenantId}/conversations
openapi: 3.1.0
info:
  title: Crescendo CXP API
  version: 1.0.0
  description: >-
    Use the Customer Experience Platform API from trusted server-side
    applications. Every accepted Create Conversation request executes; repeated
    requests can create or append another message.
servers:
  - url: https://platform.crescendo.ai
    description: Production
security: []
tags:
  - name: Conversations
    description: Create and continue customer conversations.
paths:
  /api/v1/cxm/tenants/{tenantId}/conversations:
    post:
      tags:
        - Conversations
      summary: Create or continue a conversation
      description: >-
        Use the required intake email channel and its configured AI Assistant to
        run canonical conversation resolution, then update the resolved contact,
        organization, and conversation and append the customer message. In
        Simple mode this can append to the contact's existing non-closed
        conversation; in Advanced mode each API request starts a new intake
        thread. If the request omits a subject and the resolved conversation has
        none, CXP sets `Message from {contact.email}`. A supplied assignee is
        applied only when the resolved conversation is unassigned and always
        suppresses a customer-facing Assistant turn for this request. A directly
        assigned agent may separately receive the normal internal Agent Assist
        lifecycle when configured. Without a supplied assignee, CXP starts an
        asynchronous turn only when the resolved conversation is AI-handled and
        unassigned. Requested custom fields use a separate post-intake update.
        If that update fails, CXP still returns success with a
        `CustomFieldsUpdateFailed` warning and starts any eligible Assistant
        turn. Success confirms durable intake only. It does not wait for
        notification delivery, an AI Assistant turn, Agent Assist lifecycle
        work, or outbound email delivery. The JSON request body must not exceed
        1 MiB. Every accepted POST executes; repeating a request can create or
        append another message.
      operationId: createConversation
      parameters:
        - name: tenantId
          in: path
          required: true
          description: Tenant authorized for the API key and every referenced resource.
          schema:
            type: string
            minLength: 1
            maxLength: 255
          example: tenant_demo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateConversationRequest'
            examples:
              minimal:
                summary: Minimal form submission
                value:
                  intakeChannel: support@example.com
                  contact:
                    email: jane@example.com
                  message:
                    text: Please contact me about your product.
              websiteForm:
                summary: Website contact form routed to an AI Assistant
                value:
                  intakeChannel: support@example.com
                  contact:
                    email: jane@example.com
                    phone: '+447700900123'
                    firstName: Jane
                    lastName: Doe
                  organization:
                    name: Example Ltd
                  conversation:
                    subject: Question about BCone
                    customFields:
                      product: BCone
                  message:
                    text: Can BCone be worn in the shower?
              assignedTeam:
                summary: Assign a new conversation to a team
                value:
                  intakeChannel: support@example.com
                  contact:
                    email: jane@example.com
                  conversation:
                    subject: Account access
                    assignee:
                      type: team
                      name: Technical Support
                  message:
                    text: Please help with account access.
              explicitAssignee:
                summary: >-
                  Assign an unassigned resolved conversation without starting an
                  Assistant turn
                value:
                  intakeChannel: support@example.com
                  contact:
                    email: jane@example.com
                  conversation:
                    assignee:
                      type: agent
                      id: user_demo_7f1c
                  message:
                    text: Please help with this question.
      responses:
        '200':
          description: >-
            The customer message was appended to an existing non-closed
            conversation in Simple mode. An existing assignee was preserved. If
            no assignee existed, a supplied assignee could be applied; otherwise
            an AI-handled, unassigned conversation was made eligible for an
            asynchronous Assistant turn. The optional warnings array reports a
            failed best-effort custom-field update without changing this
            successful intake result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateConversationResponse'
              examples:
                humanOwnedAppend:
                  summary: Existing human-owned conversation
                  value:
                    conversation:
                      conversationId: CX87
                      result: appended
                      subject: Account access
                      status: open
                      priority: high
                      channel: email
                      serviceEmail: null
                      assignee:
                        type: team
                        id: team_support
                        name: Technical Support
                      organizationId: null
                    contact:
                      contactId: ct_demo_123
                      result: matched
                      email: jane@example.com
                      name: Jane Doe
                      phone: null
                      organizationId: null
                assistantHandledAppend:
                  summary: Existing AI-handled conversation
                  value:
                    conversation:
                      conversationId: CX88
                      result: appended
                      subject: Product question
                      status: open
                      priority: normal
                      channel: email
                      serviceEmail: support@example.com
                      assignee: null
                      organizationId: org_demo_123
                    contact:
                      contactId: ct_demo_123
                      result: updated
                      email: jane@example.com
                      name: Jane Doe
                      phone: '+15125550100'
                      organizationId: org_demo_123
        '201':
          description: >-
            A new conversation and its first customer message were committed.
            The optional warnings array reports a failed best-effort
            custom-field update without changing this successful intake result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateConversationResponse'
              examples:
                created:
                  value:
                    conversation:
                      conversationId: CX123
                      result: created
                      subject: Question about BCone
                      status: open
                      priority: normal
                      channel: email
                      serviceEmail: support@example.com
                      assignee: null
                      organizationId: org_demo_123
                    contact:
                      contactId: ct_demo_123
                      result: created
                      email: jane@example.com
                      name: Jane Doe
                      phone: '+447700900123'
                      organizationId: org_demo_123
                customFieldsWarning:
                  summary: Conversation created, but custom fields were not updated
                  value:
                    conversation:
                      conversationId: CX124
                      result: created
                      subject: Question about BCone
                      status: open
                      priority: normal
                      channel: email
                      serviceEmail: support@example.com
                      assignee: null
                      organizationId: null
                    contact:
                      contactId: ct_demo_124
                      result: created
                      email: jane@example.com
                      name: Jane Doe
                      phone: null
                      organizationId: null
                    warnings:
                      - code: CustomFieldsUpdateFailed
                        message: >-
                          Conversation intake succeeded, but its custom fields
                          could not be updated.
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/PermissionDenied'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
      security:
        - BearerApiKey: []
components:
  schemas:
    CreateConversationRequest:
      type: object
      additionalProperties: false
      required:
        - intakeChannel
        - contact
        - message
      properties:
        intakeChannel:
          type: string
          format: email
          maxLength: 320
          description: >-
            Active tenant service-email address with a configured AI Assistant.
            CXP uses it for canonical email-style conversation resolution and,
            when eligible, asynchronous Assistant processing. It is intake
            context, not a Conversation property.
        contact:
          $ref: '#/components/schemas/ContactInput'
        organization:
          $ref: '#/components/schemas/OrganizationInput'
        conversation:
          $ref: '#/components/schemas/ConversationInput'
        message:
          $ref: '#/components/schemas/MessageInput'
    CreateConversationResponse:
      type: object
      additionalProperties: false
      required:
        - conversation
        - contact
      properties:
        conversation:
          $ref: '#/components/schemas/ConversationResult'
        contact:
          $ref: '#/components/schemas/ContactResult'
        warnings:
          type: array
          maxItems: 10
          description: >-
            Present only when intake succeeded but a best-effort post-intake
            operation failed. An eligible Assistant turn is still initiated.
          items:
            $ref: '#/components/schemas/CreateConversationWarning'
    ContactInput:
      type: object
      additionalProperties: false
      required:
        - email
      properties:
        contactId:
          type: string
          minLength: 1
          maxLength: 255
          not:
            const: anonymous
          description: >-
            Optional tenant contact lookup hint. It must be compatible with the
            supplied identity and cannot be the reserved `anonymous` Contact ID.
        email:
          type: string
          format: email
          maxLength: 320
        phone:
          type: string
          minLength: 1
          maxLength: 64
          description: >-
            Phone number accepted by CXP phone normalization and stored in E.164
            form.
        firstName:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Standard Contact first-name property. When both firstName and
            lastName are supplied without name, CXP derives the display name as
            `{firstName} {lastName}`.
        lastName:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Standard Contact last-name property. When both firstName and
            lastName are supplied without name, CXP derives the display name as
            `{firstName} {lastName}`.
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Contact display name. An explicit value takes precedence over
            display-name derivation from firstName and lastName.
    OrganizationInput:
      type: object
      additionalProperties: false
      anyOf:
        - required:
            - organizationId
        - required:
            - name
      properties:
        organizationId:
          type: string
          minLength: 1
          maxLength: 255
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Exact normalized name used to resolve or create the organization.
    ConversationInput:
      type: object
      additionalProperties: false
      properties:
        subject:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Conversation subject. If omitted and the resolved conversation has
            no subject, CXP sets `Message from {contact.email}`. An existing
            subject is preserved.
        assignee:
          allOf:
            - $ref: '#/components/schemas/AssigneeInput'
          description: >-
            Optional agent or team. CXP applies it only if the resolved
            conversation has no assignee. Supplying it always prevents a
            customer-facing Assistant turn for this request, including when an
            existing assignee is preserved. A directly assigned agent may
            separately receive the normal internal Agent Assist lifecycle when
            configured.
        priority:
          type: string
          enum:
            - low
            - normal
            - high
            - urgent
        tags:
          type: array
          maxItems: 50
          items:
            type: string
            minLength: 1
            maxLength: 100
        customFields:
          type: object
          maxProperties: 100
          additionalProperties: true
          description: Configured tenant conversation custom field values.
    MessageInput:
      type: object
      additionalProperties: false
      required:
        - text
      properties:
        text:
          type: string
          minLength: 1
          maxLength: 100000
    ConversationResult:
      type: object
      additionalProperties: false
      required:
        - conversationId
        - result
        - subject
        - status
        - priority
        - channel
        - serviceEmail
        - assignee
        - organizationId
      properties:
        conversationId:
          type: string
        result:
          type: string
          enum:
            - created
            - appended
        subject:
          type:
            - string
            - 'null'
        status:
          type: string
        priority:
          type: string
          enum:
            - low
            - normal
            - high
            - urgent
        channel:
          type: string
          const: email
        serviceEmail:
          type:
            - string
            - 'null'
          format: email
        assignee:
          oneOf:
            - $ref: '#/components/schemas/AssigneeResult'
            - type: 'null'
        organizationId:
          type:
            - string
            - 'null'
    ContactResult:
      type: object
      additionalProperties: false
      required:
        - contactId
        - result
        - email
        - name
        - phone
        - organizationId
      properties:
        contactId:
          type: string
        result:
          type: string
          enum:
            - created
            - updated
            - matched
        email:
          type: string
          format: email
        name:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
        organizationId:
          type:
            - string
            - 'null'
    CreateConversationWarning:
      type: object
      additionalProperties: false
      required:
        - code
        - message
      properties:
        code:
          type: string
          enum:
            - CustomFieldsUpdateFailed
        message:
          type: string
    Error:
      type: object
      additionalProperties: false
      required:
        - code
        - message
      properties:
        code:
          type: string
          enum:
            - BadRequest
            - InvalidCustomField
            - Unauthenticated
            - PermissionDenied
            - EmailChannelNotFound
            - AssigneeNotFound
            - NotFound
            - EmailChannelDisabled
            - ContactIdentityConflict
            - OrganizationAmbiguous
            - AssigneeAmbiguous
            - Conflict
            - PayloadTooLarge
            - RateLimitExceeded
            - BadGateway
            - ServiceUnavailable
            - GatewayTimeout
        message:
          type: string
    AssigneeInput:
      type: object
      additionalProperties: false
      required:
        - type
      oneOf:
        - required:
            - id
          not:
            required:
              - name
        - required:
            - name
          not:
            required:
              - id
      properties:
        type:
          type: string
          enum:
            - agent
            - team
        id:
          type: string
          minLength: 1
          maxLength: 255
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: Exact normalized active agent or team name.
    AssigneeResult:
      type: object
      additionalProperties: false
      required:
        - type
        - id
      properties:
        type:
          type: string
          enum:
            - agent
            - team
        id:
          type: string
        name:
          type: string
  responses:
    BadRequest:
      description: The body, a field, an unknown property, or a custom field is invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: BadRequest
            message: message.text is required
    Unauthenticated:
      description: The API key is missing, invalid, or expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: Unauthenticated
            message: Authentication required
    PermissionDenied:
      description: The API key does not authorize the tenant or required scope.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: PermissionDenied
            message: API key does not allow this operation
    NotFound:
      description: >-
        The intake email channel or requested assignee was not found in the
        authorized tenant.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: EmailChannelNotFound
            message: Email channel was not found
    Conflict:
      description: >-
        A referenced resource is inactive or identity/name resolution is
        ambiguous or conflicting.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: ContactIdentityConflict
            message: Supplied contact identities resolve to different contacts
    PayloadTooLarge:
      description: The request exceeds the 1 MiB body limit or a field-specific limit.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: PayloadTooLarge
            message: CXM API request body must not exceed 1048576 bytes
    RateLimitExceeded:
      description: The tenant/API-key/route limit was exceeded.
      headers:
        Retry-After:
          description: Seconds to wait before another request.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: RateLimitExceeded
            message: CXM API rate limit exceeded
    BadGateway:
      description: >-
        The gateway could not complete downstream transport. The durable
        mutation outcome may be unknown.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: BadGateway
            message: CXM API downstream request failed
    ServiceUnavailable:
      description: A required service or durable/configuration dependency is unavailable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: ServiceUnavailable
            message: CXM API is temporarily unavailable
    GatewayTimeout:
      description: >-
        The gateway timed out. The durable mutation outcome may be unknown, and
        retrying can duplicate effects.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: GatewayTimeout
            message: CXM API downstream request timed out
  securitySchemes:
    BearerApiKey:
      type: http
      scheme: bearer
      description: >-
        Tenant API key with `cxm:conversations.write`, `cxm:conversations.*`,
        `cxm:write`, or `cxm:*` scope. Keep it in a trusted backend; do not
        expose it in browser code.

````