> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.askelephant.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.askelephant.ai/_mcp/server.

# Create engagement

POST https://app.askelephant.ai/api/v2/engagements
Content-Type: application/json

Creates a new `CALL` or `MEETING` engagement by ingesting either a media recording from an external URL or a structured transcript timeline.

**Idempotency:** The `external_id` field is the idempotency key. Submitting the same `external_id` again — even with a different `source_system` — returns the existing engagement with a `200` response instead of creating a duplicate. If you need per-source-system uniqueness, prefix your `external_id` (e.g. `my-crm:12345`).

**Recording imports:** Provide `media_url` when you want AskElephant to fetch and transcribe a recording. The URL must be a publicly accessible HTTPS URL serving an `audio/*` or `video/*` content type. HTTP URLs, private/internal IP addresses, and non-media content types are rejected with a `422` error. The server fetches the media synchronously during request processing, so the URL must remain accessible for the duration of the request.

**Transcript-only imports:** If you do not have recording media, omit `media_url` and provide `transcript_timeline`. The timeline must include declared speakers plus timed transcript entries whose `speaker_index` values reference those speakers.

**Workflow control:** Set `run_workflows` to `true` for normal automation (workflow triggers, recap emails) or `false` to suppress workflows (e.g. for historical imports). Transcription, summarization, and tagging always run regardless.

**Owner participant:** Optionally mark exactly one participant with `is_owner: true` to assign engagement ownership to that user instead of the API-key-associated user. The marked participant must resolve to an active AskElephant user in the authenticated workspace. Resolution matches `email` first, then `phone`; users with `INACTIVE` or `NOT_INVITED` roles are not valid targets. When exactly one `is_owner: true` participant resolves successfully, the created engagement's `owner_user_id` and downstream processing use that user as owner and host. When no participant has `is_owner: true`, ownership defaults to the user associated with the API key or OAuth credential. Requests with more than one `is_owner: true` participant, or with a single owner participant that cannot resolve to an active workspace user, return HTTP `400` and do not ingest media, persist an engagement, or publish processing events. API keys or OAuth credentials without an associated user may create an engagement only when a valid explicit owner participant is provided.

**Timestamps:** If `start_at` is omitted, the current server time is used. When `transcript_timeline` is provided, `end_at` is derived from the largest `transcript_timeline.entries[].end_seconds` value, even if `media_url` is also supplied. For media-only imports (no timeline), `end_at` is derived automatically from the media duration during processing.

This operation requires the `engagements:write` scope.

Reference: https://docs.askelephant.ai/api-reference/engagements/create-engagement

## OpenAPI Specification

```yaml
openapi: 3.1.0
info:
  title: AskElephant Public API
  version: 1.0.0
paths:
  /v2/engagements:
    post:
      operationId: create-engagement
      summary: Create engagement
      description: >-
        Creates a new `CALL` or `MEETING` engagement by ingesting either a media
        recording from an external URL or a structured transcript timeline.


        **Idempotency:** The `external_id` field is the idempotency key.
        Submitting the same `external_id` again — even with a different
        `source_system` — returns the existing engagement with a `200` response
        instead of creating a duplicate. If you need per-source-system
        uniqueness, prefix your `external_id` (e.g. `my-crm:12345`).


        **Recording imports:** Provide `media_url` when you want AskElephant to
        fetch and transcribe a recording. The URL must be a publicly accessible
        HTTPS URL serving an `audio/*` or `video/*` content type. HTTP URLs,
        private/internal IP addresses, and non-media content types are rejected
        with a `422` error. The server fetches the media synchronously during
        request processing, so the URL must remain accessible for the duration
        of the request.


        **Transcript-only imports:** If you do not have recording media, omit
        `media_url` and provide `transcript_timeline`. The timeline must include
        declared speakers plus timed transcript entries whose `speaker_index`
        values reference those speakers.


        **Workflow control:** Set `run_workflows` to `true` for normal
        automation (workflow triggers, recap emails) or `false` to suppress
        workflows (e.g. for historical imports). Transcription, summarization,
        and tagging always run regardless.


        **Owner participant:** Optionally mark exactly one participant with
        `is_owner: true` to assign engagement ownership to that user instead of
        the API-key-associated user. The marked participant must resolve to an
        active AskElephant user in the authenticated workspace. Resolution
        matches `email` first, then `phone`; users with `INACTIVE` or
        `NOT_INVITED` roles are not valid targets. When exactly one `is_owner:
        true` participant resolves successfully, the created engagement's
        `owner_user_id` and downstream processing use that user as owner and
        host. When no participant has `is_owner: true`, ownership defaults to
        the user associated with the API key or OAuth credential. Requests with
        more than one `is_owner: true` participant, or with a single owner
        participant that cannot resolve to an active workspace user, return HTTP
        `400` and do not ingest media, persist an engagement, or publish
        processing events. API keys or OAuth credentials without an associated
        user may create an engagement only when a valid explicit owner
        participant is provided.


        **Timestamps:** If `start_at` is omitted, the current server time is
        used. When `transcript_timeline` is provided, `end_at` is derived from
        the largest `transcript_timeline.entries[].end_seconds` value, even if
        `media_url` is also supplied. For media-only imports (no timeline),
        `end_at` is derived automatically from the media duration during
        processing.


        This operation requires the `engagements:write` scope.
      tags:
        - engagements
      parameters:
        - name: Authorization
          in: header
          description: Bearer authentication
          required: true
          schema:
            type: string
      responses:
        '200':
          description: >-
            An engagement with the same `external_id` already exists in this
            workspace. The existing engagement is returned unchanged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/engagement_create_response'
        '400':
          description: >-
            Request validation failed, or owner participant claims are ambiguous
            or invalid. Owner failures include more than one participant with
            `is_owner: true`, or a single owner participant that does not
            resolve to an active workspace user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '401':
          description: Authentication is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '403':
          description: Authenticated but missing required scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '404':
          description: >-
            The `external_id` matches an existing engagement that the caller
            does not have permission to access (e.g., a private engagement owned
            by another user). Use a different `external_id` or request
            appropriate scopes.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '409':
          description: >-
            An engagement with the same `external_id` already exists but cannot
            be returned (e.g., the original engagement was deleted). Use a
            different `external_id`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '422':
          description: >-
            Request body validation failed, or the media URL could not be
            processed. Common causes include: unsupported engagement type,
            missing required fields, omitting both `media_url` and
            `transcript_timeline`, media URL is not accessible, media URL does
            not serve audio or video content, media URL resolves to a
            private/internal IP address, or media download timed out.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '429':
          description: Too many requests.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
        '500':
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/engagement_create_request'
servers:
  - url: https://app.askelephant.ai/api
    description: Production
  - url: https://app-staging.askelephant.ai/api
    description: Staging
components:
  schemas:
    EngagementCreateRequestType:
      type: string
      enum:
        - CALL
        - MEETING
      description: >-
        The engagement type. Only `CALL` and `MEETING` are supported for
        creation via the public API.
      title: EngagementCreateRequestType
    engagement_create_participant:
      type: object
      properties:
        name:
          type: string
          description: Display name of the participant.
        first_name:
          type: string
          description: First name of the participant.
        last_name:
          type: string
          description: Last name of the participant.
        email:
          type: string
          description: Email address of the participant.
        phone:
          type: string
          description: >-
            Phone number of the participant in E.164 format (e.g.
            `+14155552671`).
        is_owner:
          type: boolean
          description: >-
            Optional. When `true`, marks this participant as the engagement
            owner. At most one participant in the request may have `is_owner`
            set to `true`. When exactly one participant is marked as owner, that
            participant must resolve to an active AskElephant user in the
            authenticated workspace (matched by `email` first, then `phone`).
            Users with `INACTIVE` or `NOT_INVITED` roles are not valid owner
            targets. Ambiguous owner claims (more than one `is_owner: true`) or
            invalid owner claims (unresolvable or ineligible participant) return
            HTTP `400` before media ingestion, persistence, or processing
            events. When no participant has `is_owner: true`, the engagement
            owner defaults to the user associated with the API key or OAuth
            credential.
      title: engagement_create_participant
    engagement_create_transcript_timeline_speaker:
      type: object
      properties:
        index:
          type: integer
          description: Speaker index used by `entries[].speaker_index`.
        name:
          type: string
          description: Display name for this speaker.
        first_name:
          type: string
          description: Optional first name for participant matching.
        last_name:
          type: string
          description: Optional last name for participant matching.
        email:
          type: string
          format: email
          description: Optional email for participant matching.
        phone:
          type: string
          description: Optional E.164 phone number for participant matching.
      required:
        - index
        - name
      title: engagement_create_transcript_timeline_speaker
    engagement_create_transcript_timeline_sentence:
      type: object
      properties:
        text:
          type: string
        start_seconds:
          type: number
          format: double
        end_seconds:
          type: number
          format: double
      required:
        - text
        - start_seconds
        - end_seconds
      title: engagement_create_transcript_timeline_sentence
    engagement_create_transcript_timeline_entry:
      type: object
      properties:
        speaker_index:
          type: integer
          description: Must reference a speaker declared in `transcript_timeline.speakers`.
        start_seconds:
          type: number
          format: double
          description: Entry start offset from engagement start, in seconds.
        end_seconds:
          type: number
          format: double
          description: Entry end offset from engagement start, in seconds.
        sentences:
          type: array
          items:
            $ref: >-
              #/components/schemas/engagement_create_transcript_timeline_sentence
          description: Sentence-level transcript text and timing within this entry.
      required:
        - speaker_index
        - start_seconds
        - end_seconds
        - sentences
      title: engagement_create_transcript_timeline_entry
    engagement_create_transcript_timeline:
      type: object
      properties:
        speakers:
          type: array
          items:
            $ref: '#/components/schemas/engagement_create_transcript_timeline_speaker'
          description: Speakers referenced by transcript entries.
        entries:
          type: array
          items:
            $ref: '#/components/schemas/engagement_create_transcript_timeline_entry'
          description: Ordered transcript paragraphs or turns.
      required:
        - speakers
        - entries
      description: >-
        Structured transcript timeline for transcript-only engagement imports.
        Use this when you already have diarized transcript turns and no
        recording media. Each entry references a declared speaker by
        `speaker_index`; entry and sentence time ranges must be non-negative, no
        longer than 7 days, and sentence windows must stay within their parent
        entry window.
      title: engagement_create_transcript_timeline
    engagement_create_request:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/EngagementCreateRequestType'
          description: >-
            The engagement type. Only `CALL` and `MEETING` are supported for
            creation via the public API.
        title:
          type: string
          description: Display title for the engagement.
        source_system:
          type: string
          description: >-
            Identifier for the external system that produced this recording
            (e.g. `salesforce`, `custom-dialer`). Stored as metadata for
            traceability but **not** part of the idempotency key — see
            `external_id`.
        external_id:
          type: string
          description: >-
            Unique identifier for this engagement in the external system. Used
            as the idempotency key **scoped to the workspace** (not per
            `source_system`). Submitting the same `external_id` again — even
            with a different `source_system` — returns the existing engagement
            instead of creating a duplicate. If you need per-source uniqueness,
            prefix the ID yourself (e.g. `my-crm:12345`).
        media_url:
          type: string
          format: uri
          description: >-
            Publicly accessible HTTPS URL pointing to the audio or video
            recording. Required unless `transcript_timeline` is provided for a
            structured transcript-only import. The server fetches this URL
            during request processing, so it must be reachable at call time.
            Requirements: must use the `https` scheme (no `http`), must not
            resolve to private or internal IP ranges (10.x.x.x, 172.16-31.x.x,
            192.168.x.x, 127.x.x.x, 169.254.x.x, or IPv6 link-local/loopback),
            and must serve an `audio/*` or `video/*` content type.
        run_workflows:
          type: boolean
          description: >-
            Controls whether downstream automations (workflow triggers,
            post-meeting recap emails) fire for this engagement. Set to `true`
            to enable normal automation; set to `false` to suppress workflows
            (useful for historical imports). Transcription, summarization, and
            tagging always run regardless of this flag.
        start_at:
          type: string
          format: date-time
          description: >-
            ISO 8601 timestamp for when the engagement started. Defaults to the
            current server time if omitted.
        is_private:
          type: boolean
          description: >-
            Controls whether the engagement is marked as private. When `true`,
            only participants and users with `engagements:private:read` scope
            can view the engagement. Defaults to the workspace's configured
            privacy behavior if omitted.
        participants:
          type: array
          items:
            $ref: '#/components/schemas/engagement_create_participant'
          description: >-
            Optional list of participants in the engagement. Each participant
            may have a name, email, or both.
        transcript_timeline:
          $ref: '#/components/schemas/engagement_create_transcript_timeline'
        external_url:
          type: string
          description: >-
            Optional URL linking back to this engagement in the originating
            system (e.g. a dialer's call detail page). Accepts `https://`,
            `http://`, and custom app deep-link schemes such as
            `wavv://call/123`. Dangerous schemes (`javascript:`, `data:`,
            `vbscript:`, `blob:`, `file:`) are rejected. The value is stored
            as-is and returned in API responses and webhook payloads.
        transcript_text:
          type: string
          description: >-
            Deprecated. Use structured `transcript_timeline` for transcript
            imports. If provided, stored alongside the media recording; the
            media will still be processed through the transcription pipeline.
            Limited to 900,000 characters and 950,000 bytes (UTF-8). Multi-byte
            content (e.g. CJK, emoji) may hit the byte limit before the
            character limit.
      required:
        - type
        - title
        - source_system
        - external_id
        - run_workflows
      description: >-
        Create an engagement from either recording media or a structured
        transcript timeline. Provide at least one of `media_url` or
        `transcript_timeline`.
      title: engagement_create_request
    EngagementCreateResponseObject:
      type: string
      enum:
        - engagement
      title: EngagementCreateResponseObject
    EngagementCreateResponseEngagementType:
      type: string
      enum:
        - MEETING
        - CALL
        - EMAIL
        - TASK
        - NOTE
        - CALENDAR_EVENT
        - DOCUMENT
      title: EngagementCreateResponseEngagementType
    EngagementCreateResponseProcessingStatus:
      type: string
      enum:
        - PENDING
        - PROCESSING
        - COMPLETED
        - FAILED
      title: EngagementCreateResponseProcessingStatus
    crm_association:
      type: object
      properties:
        object_type:
          type: string
          description: CRM object type.
        crm_object_id:
          type: string
          description: The record ID in the source CRM system.
        source:
          type: string
          description: CRM source system.
      required:
        - object_type
        - crm_object_id
        - source
      title: crm_association
    EngagementCompanyObject:
      type: string
      enum:
        - engagement_company
      title: EngagementCompanyObject
    engagement_company:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/EngagementCompanyObject'
        id:
          type: string
        name:
          type: string
        crm_association:
          $ref: '#/components/schemas/crm_association'
          description: >-
            CRM record linked to this company. Present when the company has been
            matched to a CRM record via integration or API.
        domains:
          type: array
          items:
            type: string
      required:
        - object
        - id
        - name
        - domains
      title: engagement_company
    ContactObject:
      type: string
      enum:
        - contact
      description: Resource discriminator for contact payloads.
      title: ContactObject
    resource_ref:
      type: object
      properties:
        id:
          type: string
        object:
          type: string
      required:
        - id
        - object
      title: resource_ref
    ContactEmailsItems:
      type: object
      properties:
        email:
          type: string
          format: email
          description: Contact email address.
        is_primary:
          type: boolean
          description: Indicates whether this is the primary email address.
      required:
        - email
        - is_primary
      title: ContactEmailsItems
    ContactPhoneNumbersItems:
      type: object
      properties:
        phone_number:
          type: string
          description: Contact phone number in the source-system format.
        is_primary:
          type: boolean
          description: Indicates whether this is the primary phone number.
      required:
        - phone_number
        - is_primary
      title: ContactPhoneNumbersItems
    contact:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/ContactObject'
          description: Resource discriminator for contact payloads.
        id:
          type: string
          description: Stable AskElephant contact identifier.
        first_name:
          type:
            - string
            - 'null'
          description: Contact given name.
        last_name:
          type:
            - string
            - 'null'
          description: Contact family name.
        description:
          type: string
          description: Free-form contact summary or notes visible through the public API.
        company:
          $ref: '#/components/schemas/resource_ref'
          description: >-
            Lightweight reference to the contact's associated company when one
            exists.
        emails:
          type: array
          items:
            $ref: '#/components/schemas/ContactEmailsItems'
          description: Email addresses associated with the contact.
        phone_numbers:
          type: array
          items:
            $ref: '#/components/schemas/ContactPhoneNumbersItems'
          description: Phone numbers associated with the contact.
        crm_association:
          $ref: '#/components/schemas/crm_association'
          description: >-
            CRM record linked to this contact. Present when the contact has been
            matched to a CRM record via integration or API.
        time_zone:
          type: string
          description: IANA time zone identifier for the contact.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the contact was first created in AskElephant.
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the contact was most recently updated in AskElephant.
      required:
        - object
        - id
        - created_at
        - updated_at
      description: Public representation of a workspace contact.
      title: contact
    UserObject:
      type: string
      enum:
        - user
      title: UserObject
    UserRole:
      type: string
      enum:
        - OWNER
        - MANAGER
        - USER
        - INACTIVE
        - NOT_INVITED
      title: UserRole
    UserEmailsItems:
      type: object
      properties:
        email:
          type: string
          format: email
        is_primary:
          type: boolean
      required:
        - email
        - is_primary
      title: UserEmailsItems
    user:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/UserObject'
        id:
          type: string
        first_name:
          type:
            - string
            - 'null'
        last_name:
          type:
            - string
            - 'null'
        job_title:
          type: string
        role:
          $ref: '#/components/schemas/UserRole'
        emails:
          type: array
          items:
            $ref: '#/components/schemas/UserEmailsItems'
        time_zone:
          type: string
        last_activity_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - object
        - id
        - role
        - created_at
        - updated_at
      title: user
    EngagementActionItemObject:
      type: string
      enum:
        - engagement_action_item
      title: EngagementActionItemObject
    engagement_action_item:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/EngagementActionItemObject'
        id:
          type: string
        title:
          type: string
        description:
          type: string
        due_on:
          type:
            - string
            - 'null'
        assigned_to_user_id:
          type:
            - string
            - 'null'
        assigned_to_user_name:
          type:
            - string
            - 'null'
        assigned_to_user_email:
          type:
            - string
            - 'null'
          format: email
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - object
        - id
        - title
        - description
        - created_at
        - updated_at
      title: engagement_action_item
    EngagementSignalObject:
      type: string
      enum:
        - engagement_signal
      title: EngagementSignalObject
    engagement_signal:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/EngagementSignalObject'
        id:
          type: string
        annotation_definition_id:
          type: string
        name:
          type: string
        description:
          type:
            - string
            - 'null'
        data_type:
          type: string
        value:
          description: Any type
      required:
        - object
        - id
        - annotation_definition_id
        - name
        - data_type
        - value
      title: engagement_signal
    TagObject:
      type: string
      enum:
        - tag
      title: TagObject
    tag:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/TagObject'
        id:
          type: string
        name:
          type: string
        hex_color:
          type:
            - string
            - 'null'
        description:
          type:
            - string
            - 'null'
        auto_tagging_enabled:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - object
        - id
        - name
        - created_at
        - updated_at
      title: tag
    TranscriptTimelineObject:
      type: string
      enum:
        - transcript_timeline
      title: TranscriptTimelineObject
    transcript_timeline_speaker:
      type: object
      properties:
        first_name:
          type:
            - string
            - 'null'
        last_name:
          type:
            - string
            - 'null'
        email:
          type:
            - string
            - 'null'
          format: email
        phone:
          type:
            - string
            - 'null'
        speaking_percentage:
          type:
            - number
            - 'null'
          format: double
        sentiment:
          type:
            - number
            - 'null'
          format: double
      required:
        - first_name
        - last_name
        - email
        - phone
        - speaking_percentage
        - sentiment
      title: transcript_timeline_speaker
    TranscriptTimelineEntriesItemsSpeakerType:
      type: string
      enum:
        - contact
        - user
        - unknown
      title: TranscriptTimelineEntriesItemsSpeakerType
    TranscriptTimelineEntriesItemsSpeaker:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/TranscriptTimelineEntriesItemsSpeakerType'
        id:
          type: string
        name:
          type: string
      required:
        - type
        - id
        - name
      title: TranscriptTimelineEntriesItemsSpeaker
    TranscriptTimelineEntriesItemsSentencesItems:
      type: object
      properties:
        text:
          type: string
        start_seconds:
          type: number
          format: double
        end_seconds:
          type: number
          format: double
      required:
        - text
        - start_seconds
        - end_seconds
      title: TranscriptTimelineEntriesItemsSentencesItems
    TranscriptTimelineEntriesItems:
      type: object
      properties:
        speaker:
          $ref: '#/components/schemas/TranscriptTimelineEntriesItemsSpeaker'
        text:
          type: string
        start_seconds:
          type: number
          format: double
        end_seconds:
          type: number
          format: double
        num_words:
          type: integer
        sentences:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptTimelineEntriesItemsSentencesItems'
      required:
        - speaker
        - text
        - start_seconds
        - end_seconds
        - num_words
        - sentences
      title: TranscriptTimelineEntriesItems
    transcript_timeline:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/TranscriptTimelineObject'
        engagement_id:
          type: string
        overall_sentiment:
          type:
            - number
            - 'null'
          format: double
          description: >-
            Average sentiment score across all speakers. Null when no sentiment
            data is available.
        speakers:
          type: array
          items:
            $ref: '#/components/schemas/transcript_timeline_speaker'
          description: Speaker details indexed by their position in the entries.
        entries:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptTimelineEntriesItems'
      required:
        - object
        - engagement_id
        - speakers
        - entries
      title: transcript_timeline
    engagement_create_response:
      type: object
      properties:
        object:
          $ref: '#/components/schemas/EngagementCreateResponseObject'
        id:
          type: string
        title:
          type: string
        description:
          type: string
        engagement_type:
          $ref: '#/components/schemas/EngagementCreateResponseEngagementType'
        data_source:
          type: string
        processing_status:
          $ref: '#/components/schemas/EngagementCreateResponseProcessingStatus'
        is_internal:
          type: boolean
        is_private:
          type: boolean
          description: Indicates whether the engagement is marked private in AskElephant.
        engagement_at:
          type: string
          format: date-time
        start_at:
          type: string
          format: date-time
        end_at:
          type: string
          format: date-time
        duration_seconds:
          type: integer
        meeting_url:
          type: string
          format: uri
        external_url:
          type: string
          description: >-
            URL linking back to this engagement in the originating external
            system (e.g. a dialer's call detail page). Accepts `https://`,
            `http://`, and custom app deep-link schemes such as
            `wavv://call/123`. Present only when the engagement was created with
            an `external_url` value.
        crm_association:
          $ref: '#/components/schemas/crm_association'
          description: >-
            CRM record linked to this engagement. Present when the engagement
            has been matched to a CRM record via integration or API.
        owner_user_id:
          type: string
        host_user_id:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        transcript:
          type:
            - string
            - 'null'
          description: >-
            Full text transcript of the engagement. Only included when `expand`
            contains `transcript`.
        media_url:
          type:
            - string
            - 'null'
          format: uri
          description: >-
            Temporary signed URL for downloading the engagement recording media.
            Only included when `expand` contains `media_url`. The URL expires
            after a short period.
        companies:
          type: array
          items:
            $ref: '#/components/schemas/engagement_company'
          description: >-
            Companies associated with this engagement. Only included when
            `expand` contains `companies`.
        contacts:
          type: array
          items:
            $ref: '#/components/schemas/contact'
          description: >-
            Contact participants associated with this engagement. Only included
            when `expand` contains `contacts`.
        owner:
          oneOf:
            - $ref: '#/components/schemas/user'
            - type: 'null'
          description: >-
            Workspace user who owns this engagement. Only included when `expand`
            contains `owner`.
        action_items:
          type: array
          items:
            $ref: '#/components/schemas/engagement_action_item'
          description: >-
            Action items created from this engagement. Only included when
            `expand` contains `action_items`.
        signals:
          type: array
          items:
            $ref: '#/components/schemas/engagement_signal'
          description: >-
            Signals (annotations) extracted from this engagement. Only included
            when `expand` contains `signals`.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/tag'
          description: >-
            Tags applied to this engagement. Only included when `expand`
            contains `tags`.
        transcript_timeline:
          $ref: '#/components/schemas/transcript_timeline'
          description: >-
            Structured transcript timeline returned by `POST /v2/engagements`.
            When no structured timeline exists yet, this is returned as an empty
            transcript timeline with no speakers or entries. For
            read-after-create retrieval, use `GET
            /v2/engagements/{engagement_id}/transcript_timeline`.
      required:
        - object
        - id
        - title
        - engagement_type
        - processing_status
        - is_private
        - created_at
        - updated_at
        - transcript_timeline
      title: engagement_create_response
    error_item:
      type: object
      properties:
        field:
          type: string
          description: Request field or parameter associated with the error.
        code:
          type: string
          description: Stable machine-readable error code.
        message:
          type: string
          description: Human-readable explanation of the error.
      required:
        - code
        - message
      description: Structured validation or field-level error detail.
      title: error_item
    error:
      type: object
      properties:
        type:
          type: string
          format: uri
          description: Stable URI identifying the error category.
        title:
          type: string
          description: Short human-readable summary of the error.
        status:
          type: integer
          description: HTTP status code for this error response.
        detail:
          type: string
          description: Human-readable explanation specific to this request.
        request_id:
          type: string
          description: Correlation identifier for support and debugging.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/error_item'
          description: Optional field-level validation errors.
      required:
        - type
        - title
        - status
        - detail
        - request_id
      description: RFC 9457 problem details response returned for client-visible failures.
      title: error
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer

```

## Examples

### Structured transcript-only import



**Request**

```json
{
  "type": "MEETING",
  "title": "Customer kickoff",
  "source_system": "crm-transcripts",
  "external_id": "transcript_98765",
  "run_workflows": false,
  "start_at": "2026-06-12T17:00:00Z",
  "transcript_timeline": {
    "speakers": [
      {
        "index": 0,
        "name": "Alice Example",
        "first_name": "Alice",
        "last_name": "Example",
        "email": "alice@example.com"
      },
      {
        "index": 1,
        "name": "Bob Example",
        "email": "bob@example.com"
      }
    ],
    "entries": [
      {
        "speaker_index": 0,
        "start_seconds": 0,
        "end_seconds": 2.5,
        "sentences": [
          {
            "text": "Welcome to the kickoff.",
            "start_seconds": 0,
            "end_seconds": 2.5
          }
        ]
      },
      {
        "speaker_index": 1,
        "start_seconds": 2.5,
        "end_seconds": 5,
        "sentences": [
          {
            "text": "Thanks, happy to be here.",
            "start_seconds": 2.5,
            "end_seconds": 5
          }
        ]
      }
    ]
  }
}
```

**Response**

```json
{
  "object": "engagement",
  "id": "string",
  "title": "string",
  "engagement_type": "MEETING",
  "processing_status": "PENDING",
  "is_private": true,
  "created_at": "2024-01-15T09:30:00Z",
  "updated_at": "2024-01-15T09:30:00Z",
  "transcript_timeline": {
    "object": "transcript_timeline",
    "engagement_id": "string",
    "speakers": [
      {
        "first_name": "string",
        "last_name": "string",
        "email": "string",
        "phone": "string",
        "speaking_percentage": 1.1,
        "sentiment": 1.1
      }
    ],
    "entries": [
      {
        "speaker": {
          "type": "contact",
          "id": "string",
          "name": "string"
        },
        "text": "string",
        "start_seconds": 1.1,
        "end_seconds": 1.1,
        "num_words": 1,
        "sentences": [
          {
            "text": "string",
            "start_seconds": 1.1,
            "end_seconds": 1.1
          }
        ]
      }
    ],
    "overall_sentiment": 1.1
  },
  "description": "string",
  "data_source": "string",
  "is_internal": true,
  "engagement_at": "2024-01-15T09:30:00Z",
  "start_at": "2024-01-15T09:30:00Z",
  "end_at": "2024-01-15T09:30:00Z",
  "duration_seconds": 1,
  "meeting_url": "string",
  "external_url": "string",
  "crm_association": {
    "object_type": "string",
    "crm_object_id": "string",
    "source": "string"
  },
  "owner_user_id": "string",
  "host_user_id": "string",
  "transcript": "string",
  "media_url": "string",
  "companies": [
    {
      "object": "engagement_company",
      "id": "string",
      "name": "string",
      "domains": [
        "string"
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      }
    }
  ],
  "contacts": [
    {
      "object": "contact",
      "id": "cnt_01HQY3JMS2QAXJGX6X7CH7CM6X",
      "created_at": "2026-03-01T12:00:00Z",
      "updated_at": "2026-03-04T18:25:00Z",
      "first_name": "Ada",
      "last_name": "Lovelace",
      "description": "Primary customer contact for analytical projects.",
      "company": {
        "id": "string",
        "object": "string"
      },
      "emails": [
        {
          "email": "ada@analytical.engine",
          "is_primary": true
        }
      ],
      "phone_numbers": [
        {
          "phone_number": "+1-555-0100",
          "is_primary": true
        }
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      },
      "time_zone": "America/Los_Angeles"
    }
  ],
  "owner": {
    "object": "user",
    "id": "string",
    "role": "OWNER",
    "created_at": "2024-01-15T09:30:00Z",
    "updated_at": "2024-01-15T09:30:00Z",
    "first_name": "string",
    "last_name": "string",
    "job_title": "string",
    "emails": [
      {
        "email": "string",
        "is_primary": true
      }
    ],
    "time_zone": "string",
    "last_activity_at": "2024-01-15T09:30:00Z"
  },
  "action_items": [
    {
      "object": "engagement_action_item",
      "id": "string",
      "title": "string",
      "description": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "due_on": "string",
      "assigned_to_user_id": "string",
      "assigned_to_user_name": "string",
      "assigned_to_user_email": "string"
    }
  ],
  "signals": [
    {
      "object": "engagement_signal",
      "id": "string",
      "annotation_definition_id": "string",
      "name": "string",
      "data_type": "string",
      "description": "string"
    }
  ],
  "tags": [
    {
      "object": "tag",
      "id": "string",
      "name": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "hex_color": "string",
      "description": "string",
      "auto_tagging_enabled": true
    }
  ]
}
```

**SDK Code**

```python Structured transcript-only import
import requests

url = "https://app.askelephant.ai/api/v2/engagements"

payload = {
    "type": "MEETING",
    "title": "Customer kickoff",
    "source_system": "crm-transcripts",
    "external_id": "transcript_98765",
    "run_workflows": False,
    "start_at": "2026-06-12T17:00:00Z",
    "transcript_timeline": {
        "speakers": [
            {
                "index": 0,
                "name": "Alice Example",
                "first_name": "Alice",
                "last_name": "Example",
                "email": "alice@example.com"
            },
            {
                "index": 1,
                "name": "Bob Example",
                "email": "bob@example.com"
            }
        ],
        "entries": [
            {
                "speaker_index": 0,
                "start_seconds": 0,
                "end_seconds": 2.5,
                "sentences": [
                    {
                        "text": "Welcome to the kickoff.",
                        "start_seconds": 0,
                        "end_seconds": 2.5
                    }
                ]
            },
            {
                "speaker_index": 1,
                "start_seconds": 2.5,
                "end_seconds": 5,
                "sentences": [
                    {
                        "text": "Thanks, happy to be here.",
                        "start_seconds": 2.5,
                        "end_seconds": 5
                    }
                ]
            }
        ]
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Structured transcript-only import
const url = 'https://app.askelephant.ai/api/v2/engagements';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"type":"MEETING","title":"Customer kickoff","source_system":"crm-transcripts","external_id":"transcript_98765","run_workflows":false,"start_at":"2026-06-12T17:00:00Z","transcript_timeline":{"speakers":[{"index":0,"name":"Alice Example","first_name":"Alice","last_name":"Example","email":"alice@example.com"},{"index":1,"name":"Bob Example","email":"bob@example.com"}],"entries":[{"speaker_index":0,"start_seconds":0,"end_seconds":2.5,"sentences":[{"text":"Welcome to the kickoff.","start_seconds":0,"end_seconds":2.5}]},{"speaker_index":1,"start_seconds":2.5,"end_seconds":5,"sentences":[{"text":"Thanks, happy to be here.","start_seconds":2.5,"end_seconds":5}]}]}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Structured transcript-only import
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://app.askelephant.ai/api/v2/engagements"

	payload := strings.NewReader("{\n  \"type\": \"MEETING\",\n  \"title\": \"Customer kickoff\",\n  \"source_system\": \"crm-transcripts\",\n  \"external_id\": \"transcript_98765\",\n  \"run_workflows\": false,\n  \"start_at\": \"2026-06-12T17:00:00Z\",\n  \"transcript_timeline\": {\n    \"speakers\": [\n      {\n        \"index\": 0,\n        \"name\": \"Alice Example\",\n        \"first_name\": \"Alice\",\n        \"last_name\": \"Example\",\n        \"email\": \"alice@example.com\"\n      },\n      {\n        \"index\": 1,\n        \"name\": \"Bob Example\",\n        \"email\": \"bob@example.com\"\n      }\n    ],\n    \"entries\": [\n      {\n        \"speaker_index\": 0,\n        \"start_seconds\": 0,\n        \"end_seconds\": 2.5,\n        \"sentences\": [\n          {\n            \"text\": \"Welcome to the kickoff.\",\n            \"start_seconds\": 0,\n            \"end_seconds\": 2.5\n          }\n        ]\n      },\n      {\n        \"speaker_index\": 1,\n        \"start_seconds\": 2.5,\n        \"end_seconds\": 5,\n        \"sentences\": [\n          {\n            \"text\": \"Thanks, happy to be here.\",\n            \"start_seconds\": 2.5,\n            \"end_seconds\": 5\n          }\n        ]\n      }\n    ]\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Structured transcript-only import
require 'uri'
require 'net/http'

url = URI("https://app.askelephant.ai/api/v2/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"type\": \"MEETING\",\n  \"title\": \"Customer kickoff\",\n  \"source_system\": \"crm-transcripts\",\n  \"external_id\": \"transcript_98765\",\n  \"run_workflows\": false,\n  \"start_at\": \"2026-06-12T17:00:00Z\",\n  \"transcript_timeline\": {\n    \"speakers\": [\n      {\n        \"index\": 0,\n        \"name\": \"Alice Example\",\n        \"first_name\": \"Alice\",\n        \"last_name\": \"Example\",\n        \"email\": \"alice@example.com\"\n      },\n      {\n        \"index\": 1,\n        \"name\": \"Bob Example\",\n        \"email\": \"bob@example.com\"\n      }\n    ],\n    \"entries\": [\n      {\n        \"speaker_index\": 0,\n        \"start_seconds\": 0,\n        \"end_seconds\": 2.5,\n        \"sentences\": [\n          {\n            \"text\": \"Welcome to the kickoff.\",\n            \"start_seconds\": 0,\n            \"end_seconds\": 2.5\n          }\n        ]\n      },\n      {\n        \"speaker_index\": 1,\n        \"start_seconds\": 2.5,\n        \"end_seconds\": 5,\n        \"sentences\": [\n          {\n            \"text\": \"Thanks, happy to be here.\",\n            \"start_seconds\": 2.5,\n            \"end_seconds\": 5\n          }\n        ]\n      }\n    ]\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java Structured transcript-only import
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://app.askelephant.ai/api/v2/engagements")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"type\": \"MEETING\",\n  \"title\": \"Customer kickoff\",\n  \"source_system\": \"crm-transcripts\",\n  \"external_id\": \"transcript_98765\",\n  \"run_workflows\": false,\n  \"start_at\": \"2026-06-12T17:00:00Z\",\n  \"transcript_timeline\": {\n    \"speakers\": [\n      {\n        \"index\": 0,\n        \"name\": \"Alice Example\",\n        \"first_name\": \"Alice\",\n        \"last_name\": \"Example\",\n        \"email\": \"alice@example.com\"\n      },\n      {\n        \"index\": 1,\n        \"name\": \"Bob Example\",\n        \"email\": \"bob@example.com\"\n      }\n    ],\n    \"entries\": [\n      {\n        \"speaker_index\": 0,\n        \"start_seconds\": 0,\n        \"end_seconds\": 2.5,\n        \"sentences\": [\n          {\n            \"text\": \"Welcome to the kickoff.\",\n            \"start_seconds\": 0,\n            \"end_seconds\": 2.5\n          }\n        ]\n      },\n      {\n        \"speaker_index\": 1,\n        \"start_seconds\": 2.5,\n        \"end_seconds\": 5,\n        \"sentences\": [\n          {\n            \"text\": \"Thanks, happy to be here.\",\n            \"start_seconds\": 2.5,\n            \"end_seconds\": 5\n          }\n        ]\n      }\n    ]\n  }\n}")
  .asString();
```

```php Structured transcript-only import
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://app.askelephant.ai/api/v2/engagements', [
  'body' => '{
  "type": "MEETING",
  "title": "Customer kickoff",
  "source_system": "crm-transcripts",
  "external_id": "transcript_98765",
  "run_workflows": false,
  "start_at": "2026-06-12T17:00:00Z",
  "transcript_timeline": {
    "speakers": [
      {
        "index": 0,
        "name": "Alice Example",
        "first_name": "Alice",
        "last_name": "Example",
        "email": "alice@example.com"
      },
      {
        "index": 1,
        "name": "Bob Example",
        "email": "bob@example.com"
      }
    ],
    "entries": [
      {
        "speaker_index": 0,
        "start_seconds": 0,
        "end_seconds": 2.5,
        "sentences": [
          {
            "text": "Welcome to the kickoff.",
            "start_seconds": 0,
            "end_seconds": 2.5
          }
        ]
      },
      {
        "speaker_index": 1,
        "start_seconds": 2.5,
        "end_seconds": 5,
        "sentences": [
          {
            "text": "Thanks, happy to be here.",
            "start_seconds": 2.5,
            "end_seconds": 5
          }
        ]
      }
    ]
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Structured transcript-only import
using RestSharp;

var client = new RestClient("https://app.askelephant.ai/api/v2/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"type\": \"MEETING\",\n  \"title\": \"Customer kickoff\",\n  \"source_system\": \"crm-transcripts\",\n  \"external_id\": \"transcript_98765\",\n  \"run_workflows\": false,\n  \"start_at\": \"2026-06-12T17:00:00Z\",\n  \"transcript_timeline\": {\n    \"speakers\": [\n      {\n        \"index\": 0,\n        \"name\": \"Alice Example\",\n        \"first_name\": \"Alice\",\n        \"last_name\": \"Example\",\n        \"email\": \"alice@example.com\"\n      },\n      {\n        \"index\": 1,\n        \"name\": \"Bob Example\",\n        \"email\": \"bob@example.com\"\n      }\n    ],\n    \"entries\": [\n      {\n        \"speaker_index\": 0,\n        \"start_seconds\": 0,\n        \"end_seconds\": 2.5,\n        \"sentences\": [\n          {\n            \"text\": \"Welcome to the kickoff.\",\n            \"start_seconds\": 0,\n            \"end_seconds\": 2.5\n          }\n        ]\n      },\n      {\n        \"speaker_index\": 1,\n        \"start_seconds\": 2.5,\n        \"end_seconds\": 5,\n        \"sentences\": [\n          {\n            \"text\": \"Thanks, happy to be here.\",\n            \"start_seconds\": 2.5,\n            \"end_seconds\": 5\n          }\n        ]\n      }\n    ]\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Structured transcript-only import
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "type": "MEETING",
  "title": "Customer kickoff",
  "source_system": "crm-transcripts",
  "external_id": "transcript_98765",
  "run_workflows": false,
  "start_at": "2026-06-12T17:00:00Z",
  "transcript_timeline": [
    "speakers": [
      [
        "index": 0,
        "name": "Alice Example",
        "first_name": "Alice",
        "last_name": "Example",
        "email": "alice@example.com"
      ],
      [
        "index": 1,
        "name": "Bob Example",
        "email": "bob@example.com"
      ]
    ],
    "entries": [
      [
        "speaker_index": 0,
        "start_seconds": 0,
        "end_seconds": 2.5,
        "sentences": [
          [
            "text": "Welcome to the kickoff.",
            "start_seconds": 0,
            "end_seconds": 2.5
          ]
        ]
      ],
      [
        "speaker_index": 1,
        "start_seconds": 2.5,
        "end_seconds": 5,
        "sentences": [
          [
            "text": "Thanks, happy to be here.",
            "start_seconds": 2.5,
            "end_seconds": 5
          ]
        ]
      ]
    ]
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://app.askelephant.ai/api/v2/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Example 2



**Request**

```json
{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}
```

**Response**

```json
{
  "object": "engagement",
  "id": "string",
  "title": "string",
  "engagement_type": "MEETING",
  "processing_status": "PENDING",
  "is_private": true,
  "created_at": "2024-01-15T09:30:00Z",
  "updated_at": "2024-01-15T09:30:00Z",
  "transcript_timeline": {
    "object": "transcript_timeline",
    "engagement_id": "string",
    "speakers": [
      {
        "first_name": "string",
        "last_name": "string",
        "email": "string",
        "phone": "string",
        "speaking_percentage": 1.1,
        "sentiment": 1.1
      }
    ],
    "entries": [
      {
        "speaker": {
          "type": "contact",
          "id": "string",
          "name": "string"
        },
        "text": "string",
        "start_seconds": 1.1,
        "end_seconds": 1.1,
        "num_words": 1,
        "sentences": [
          {
            "text": "string",
            "start_seconds": 1.1,
            "end_seconds": 1.1
          }
        ]
      }
    ],
    "overall_sentiment": 1.1
  },
  "description": "string",
  "data_source": "string",
  "is_internal": true,
  "engagement_at": "2024-01-15T09:30:00Z",
  "start_at": "2024-01-15T09:30:00Z",
  "end_at": "2024-01-15T09:30:00Z",
  "duration_seconds": 1,
  "meeting_url": "string",
  "external_url": "string",
  "crm_association": {
    "object_type": "string",
    "crm_object_id": "string",
    "source": "string"
  },
  "owner_user_id": "string",
  "host_user_id": "string",
  "transcript": "string",
  "media_url": "string",
  "companies": [
    {
      "object": "engagement_company",
      "id": "string",
      "name": "string",
      "domains": [
        "string"
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      }
    }
  ],
  "contacts": [
    {
      "object": "contact",
      "id": "cnt_01HQY3JMS2QAXJGX6X7CH7CM6X",
      "created_at": "2026-03-01T12:00:00Z",
      "updated_at": "2026-03-04T18:25:00Z",
      "first_name": "Ada",
      "last_name": "Lovelace",
      "description": "Primary customer contact for analytical projects.",
      "company": {
        "id": "string",
        "object": "string"
      },
      "emails": [
        {
          "email": "ada@analytical.engine",
          "is_primary": true
        }
      ],
      "phone_numbers": [
        {
          "phone_number": "+1-555-0100",
          "is_primary": true
        }
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      },
      "time_zone": "America/Los_Angeles"
    }
  ],
  "owner": {
    "object": "user",
    "id": "string",
    "role": "OWNER",
    "created_at": "2024-01-15T09:30:00Z",
    "updated_at": "2024-01-15T09:30:00Z",
    "first_name": "string",
    "last_name": "string",
    "job_title": "string",
    "emails": [
      {
        "email": "string",
        "is_primary": true
      }
    ],
    "time_zone": "string",
    "last_activity_at": "2024-01-15T09:30:00Z"
  },
  "action_items": [
    {
      "object": "engagement_action_item",
      "id": "string",
      "title": "string",
      "description": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "due_on": "string",
      "assigned_to_user_id": "string",
      "assigned_to_user_name": "string",
      "assigned_to_user_email": "string"
    }
  ],
  "signals": [
    {
      "object": "engagement_signal",
      "id": "string",
      "annotation_definition_id": "string",
      "name": "string",
      "data_type": "string",
      "description": "string"
    }
  ],
  "tags": [
    {
      "object": "tag",
      "id": "string",
      "name": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "hex_color": "string",
      "description": "string",
      "auto_tagging_enabled": true
    }
  ]
}
```

**SDK Code**

```python
import requests

url = "https://app.askelephant.ai/api/v2/engagements"

payload = {
    "type": "CALL",
    "title": "Discovery call",
    "source_system": "custom-dialer",
    "external_id": "call_12345",
    "run_workflows": True,
    "media_url": "https://recordings.example.com/call_12345.mp3",
    "start_at": "2026-06-12T17:00:00Z"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://app.askelephant.ai/api/v2/engagements';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"type":"CALL","title":"Discovery call","source_system":"custom-dialer","external_id":"call_12345","run_workflows":true,"media_url":"https://recordings.example.com/call_12345.mp3","start_at":"2026-06-12T17:00:00Z"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://app.askelephant.ai/api/v2/engagements"

	payload := strings.NewReader("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://app.askelephant.ai/api/v2/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://app.askelephant.ai/api/v2/engagements")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://app.askelephant.ai/api/v2/engagements', [
  'body' => '{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://app.askelephant.ai/api/v2/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://app.askelephant.ai/api/v2/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Example 3



**Request**

```json
{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}
```

**Response**

```json
{
  "object": "engagement",
  "id": "string",
  "title": "string",
  "engagement_type": "MEETING",
  "processing_status": "PENDING",
  "is_private": true,
  "created_at": "2024-01-15T09:30:00Z",
  "updated_at": "2024-01-15T09:30:00Z",
  "transcript_timeline": {
    "object": "transcript_timeline",
    "engagement_id": "string",
    "speakers": [
      {
        "first_name": "string",
        "last_name": "string",
        "email": "string",
        "phone": "string",
        "speaking_percentage": 1.1,
        "sentiment": 1.1
      }
    ],
    "entries": [
      {
        "speaker": {
          "type": "contact",
          "id": "string",
          "name": "string"
        },
        "text": "string",
        "start_seconds": 1.1,
        "end_seconds": 1.1,
        "num_words": 1,
        "sentences": [
          {
            "text": "string",
            "start_seconds": 1.1,
            "end_seconds": 1.1
          }
        ]
      }
    ],
    "overall_sentiment": 1.1
  },
  "description": "string",
  "data_source": "string",
  "is_internal": true,
  "engagement_at": "2024-01-15T09:30:00Z",
  "start_at": "2024-01-15T09:30:00Z",
  "end_at": "2024-01-15T09:30:00Z",
  "duration_seconds": 1,
  "meeting_url": "string",
  "external_url": "string",
  "crm_association": {
    "object_type": "string",
    "crm_object_id": "string",
    "source": "string"
  },
  "owner_user_id": "string",
  "host_user_id": "string",
  "transcript": "string",
  "media_url": "string",
  "companies": [
    {
      "object": "engagement_company",
      "id": "string",
      "name": "string",
      "domains": [
        "string"
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      }
    }
  ],
  "contacts": [
    {
      "object": "contact",
      "id": "cnt_01HQY3JMS2QAXJGX6X7CH7CM6X",
      "created_at": "2026-03-01T12:00:00Z",
      "updated_at": "2026-03-04T18:25:00Z",
      "first_name": "Ada",
      "last_name": "Lovelace",
      "description": "Primary customer contact for analytical projects.",
      "company": {
        "id": "string",
        "object": "string"
      },
      "emails": [
        {
          "email": "ada@analytical.engine",
          "is_primary": true
        }
      ],
      "phone_numbers": [
        {
          "phone_number": "+1-555-0100",
          "is_primary": true
        }
      ],
      "crm_association": {
        "object_type": "string",
        "crm_object_id": "string",
        "source": "string"
      },
      "time_zone": "America/Los_Angeles"
    }
  ],
  "owner": {
    "object": "user",
    "id": "string",
    "role": "OWNER",
    "created_at": "2024-01-15T09:30:00Z",
    "updated_at": "2024-01-15T09:30:00Z",
    "first_name": "string",
    "last_name": "string",
    "job_title": "string",
    "emails": [
      {
        "email": "string",
        "is_primary": true
      }
    ],
    "time_zone": "string",
    "last_activity_at": "2024-01-15T09:30:00Z"
  },
  "action_items": [
    {
      "object": "engagement_action_item",
      "id": "string",
      "title": "string",
      "description": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "due_on": "string",
      "assigned_to_user_id": "string",
      "assigned_to_user_name": "string",
      "assigned_to_user_email": "string"
    }
  ],
  "signals": [
    {
      "object": "engagement_signal",
      "id": "string",
      "annotation_definition_id": "string",
      "name": "string",
      "data_type": "string",
      "description": "string"
    }
  ],
  "tags": [
    {
      "object": "tag",
      "id": "string",
      "name": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": "2024-01-15T09:30:00Z",
      "hex_color": "string",
      "description": "string",
      "auto_tagging_enabled": true
    }
  ]
}
```

**SDK Code**

```python
import requests

url = "https://app.askelephant.ai/api/v2/engagements"

payload = {
    "type": "CALL",
    "title": "Discovery call",
    "source_system": "custom-dialer",
    "external_id": "call_12345",
    "run_workflows": True,
    "media_url": "https://recordings.example.com/call_12345.mp3",
    "start_at": "2026-06-12T17:00:00Z"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://app.askelephant.ai/api/v2/engagements';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"type":"CALL","title":"Discovery call","source_system":"custom-dialer","external_id":"call_12345","run_workflows":true,"media_url":"https://recordings.example.com/call_12345.mp3","start_at":"2026-06-12T17:00:00Z"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://app.askelephant.ai/api/v2/engagements"

	payload := strings.NewReader("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://app.askelephant.ai/api/v2/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://app.askelephant.ai/api/v2/engagements")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://app.askelephant.ai/api/v2/engagements', [
  'body' => '{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://app.askelephant.ai/api/v2/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://app.askelephant.ai/api/v2/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Example 4



**Request**

```json
{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}
```

**Response**

```json
{}
```

**SDK Code**

```python
import requests

url = "https://app.askelephant.ai/api/v2/engagements"

payload = {
    "type": "CALL",
    "title": "Discovery call",
    "source_system": "custom-dialer",
    "external_id": "call_12345",
    "run_workflows": True,
    "media_url": "https://recordings.example.com/call_12345.mp3",
    "start_at": "2026-06-12T17:00:00Z"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://app.askelephant.ai/api/v2/engagements';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"type":"CALL","title":"Discovery call","source_system":"custom-dialer","external_id":"call_12345","run_workflows":true,"media_url":"https://recordings.example.com/call_12345.mp3","start_at":"2026-06-12T17:00:00Z"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://app.askelephant.ai/api/v2/engagements"

	payload := strings.NewReader("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://app.askelephant.ai/api/v2/engagements")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://app.askelephant.ai/api/v2/engagements")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://app.askelephant.ai/api/v2/engagements', [
  'body' => '{
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://app.askelephant.ai/api/v2/engagements");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"type\": \"CALL\",\n  \"title\": \"Discovery call\",\n  \"source_system\": \"custom-dialer\",\n  \"external_id\": \"call_12345\",\n  \"run_workflows\": true,\n  \"media_url\": \"https://recordings.example.com/call_12345.mp3\",\n  \"start_at\": \"2026-06-12T17:00:00Z\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "type": "CALL",
  "title": "Discovery call",
  "source_system": "custom-dialer",
  "external_id": "call_12345",
  "run_workflows": true,
  "media_url": "https://recordings.example.com/call_12345.mp3",
  "start_at": "2026-06-12T17:00:00Z"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://app.askelephant.ai/api/v2/engagements")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```