> ## 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 a contact

> Create one contact without updating or merging an existing record. Requires cxm:contacts.write. At least one primary email or phone is required; secondary addresses alone are insufficient. Checks all supplied primary and secondary identities against stored primary and secondary values and returns one blocking contact ID. ID conflicts take precedence. IDs and primary emails have database uniqueness protection; concurrent phone/secondary conflicts may escape lookup checks. Deduplicate and serialize overlapping identities. Requires the matching tenant API-key write scope or broader scope. Maximum JSON request body: 1 MiB, subject to a lower configured gateway limit. Unknown fields are rejected. Each accepted request executes; no idempotency or replay guarantee. A timeout may occur after commit.



## OpenAPI

````yaml /api-reference/openapi-v1.json post /api/v1/cxm/tenants/{tenantId}/contacts
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 to create Contacts and Organizations, import historical
    Conversations, create live Conversations, read projected detail and stored
    history, update operational fields, assign work, and add internal notes.
    Writes execute independently; repeating a write may repeat its effects.
servers:
  - url: https://platform.crescendo.ai
    description: Production
security: []
tags:
  - name: Conversations
    description: Create, import, continue, and manage customer conversations.
  - name: Contacts
    description: Create contacts for backend integrations and historical imports.
  - name: Organizations
    description: Create organizations for historical conversation references.
paths:
  /api/v1/cxm/tenants/{tenantId}/contacts:
    post:
      tags:
        - Contacts
      summary: Create a contact
      description: >-
        Create one contact without updating or merging an existing record.
        Requires cxm:contacts.write. At least one primary email or phone is
        required; secondary addresses alone are insufficient. Checks all
        supplied primary and secondary identities against stored primary and
        secondary values and returns one blocking contact ID. ID conflicts take
        precedence. IDs and primary emails have database uniqueness protection;
        concurrent phone/secondary conflicts may escape lookup checks.
        Deduplicate and serialize overlapping identities. Requires the matching
        tenant API-key write scope or broader scope. Maximum JSON request body:
        1 MiB, subject to a lower configured gateway limit. Unknown fields are
        rejected. Each accepted request executes; no idempotency or replay
        guarantee. A timeout may occur after commit.
      operationId: createContact
      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/CreateContactRequest'
            example:
              contact:
                contactId: external-contact-123
                email: jane@example.com
                firstName: Jane
                lastName: Doe
                tags:
                  - historical-import
                secondaryEmails:
                  - jane.alt@example.com
      responses:
        '201':
          description: Contact created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateContactResponse'
              example:
                contact:
                  contactId: external-contact-123
                  result: created
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          $ref: '#/components/responses/PermissionDenied'
        '409':
          description: A supplied ID or identity conflicts with existing tenant data.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                id:
                  value:
                    code: ContactIdConflict
                    message: Contact ID already exists
                    existingContactId: external-contact-123
                identity:
                  value:
                    code: ContactIdentityConflict
                    message: A contact with a supplied email or phone already exists
                    existingContactId: ct_existing
        '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:
    CreateContactRequest:
      type: object
      additionalProperties: false
      required:
        - contact
      properties:
        contact:
          $ref: '#/components/schemas/CreateContactInput'
    CreateContactResponse:
      type: object
      additionalProperties: false
      required:
        - contact
      properties:
        contact:
          type: object
          additionalProperties: false
          required:
            - contactId
            - result
          properties:
            contactId:
              type: string
              minLength: 1
              maxLength: 255
            result:
              type: string
              const: created
    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
            - ContactIdConflict
            - OrganizationIdConflict
            - ConversationIdConflict
            - ContactNotFound
            - OrganizationNotFound
            - ContactReadOnly
            - TeamNotFound
            - TeamAmbiguous
        message:
          type: string
        existingContactId:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            One blocking record ID in a corresponding create/import conflict
            response. It does not establish that an earlier request had the same
            payload.
        existingOrganizationId:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            One blocking record ID in a corresponding create/import conflict
            response. It does not establish that an earlier request had the same
            payload.
        existingConversationId:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            One blocking record ID in a corresponding create/import conflict
            response. It does not establish that an earlier request had the same
            payload.
    CreateContactInput:
      type: object
      additionalProperties: false
      properties:
        contactId:
          type: string
          minLength: 1
          maxLength: 255
          description: >-
            Optional preserved ID. Omission generates ct_<uuid>; anonymous is
            reserved.
          not:
            const: anonymous
        email:
          type: string
          format: email
          maxLength: 320
          description: >-
            Primary email; trimmed, validated and normalized to lowercase. At
            least one nonblank primary email or phone is required.
          minLength: 1
        phone:
          type: string
          minLength: 1
          maxLength: 64
          description: >-
            Primary phone, normalized to E.164. Unsupported extensions are
            rejected. At least one nonblank primary email or phone is required.
        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.
        tags:
          type: array
          maxItems: 50
          items:
            type: string
            minLength: 1
            maxLength: 100
          description: Case-insensitive deduplication; whitespace-only values are invalid.
        secondaryEmails:
          type: array
          maxItems: 50
          items:
            type: string
            format: email
            minLength: 1
            maxLength: 320
          description: >-
            Normalized and deduplicated; repeats of the primary email are
            removed.
        secondaryPhones:
          type: array
          maxItems: 50
          items:
            type: string
            minLength: 1
            maxLength: 64
            description: Normalized to E.164.
          description: >-
            Normalized and deduplicated; repeats of the primary phone are
            removed.
      anyOf:
        - required:
            - email
        - required:
            - phone
      description: >-
        Create-only contact fields. Secondary addresses alone cannot satisfy the
        required primary email or phone. No organization, custom fields or
        historical timestamps.
  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
    PayloadTooLarge:
      description: >-
        The request exceeds the endpoint body limit or a lower configured
        gateway 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 the operation's scope: `cxm:conversations.read`,
        `cxm:conversations.write`, `cxm:contacts.write`, or
        `cxm:organizations.write`. Corresponding resource wildcards and broader
        `cxm:read`, `cxm:write`, or `cxm:*` scopes apply. Keep it in a trusted
        backend; do not expose it in browser code.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.