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

# Conversations

> List, retrieve, sync, analyze, update, and delete conversation records

## List conversations

Retrieves a paginated list of conversations. Standard users see only conversations belonging to their own genies. Admin users see all conversations.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `all`
</ParamField>

<ParamField body="data" type="object">
  <Expandable title="properties">
    <ParamField body="agentIds" type="string[]">
      Filter conversations to specific genies by UUID array. When omitted, returns conversations for all genies the user owns.
    </ParamField>

    <ParamField body="limit" type="number">
      Maximum number of records to return per page. Defaults to `30`, maximum `500`.
    </ParamField>

    <ParamField body="cursor" type="string">
      Cursor returned from a previous response as `nextCursor`. Pass it unchanged to fetch the next page.
    </ParamField>

    <ParamField body="timeRange" type="string">
      Relative time filter. Format: `{value}{unit}` where unit is `h` (hours), `d` (days), or `m` (minutes). For example, `"24h"` returns conversations from the last 24 hours.
    </ParamField>

    <ParamField body="excludeMailbox" type="boolean">
      When `true`, excludes conversations with `type = "mailbox"`.
    </ParamField>

    <ParamField body="conversationType" type="string">
      Filter by conversation type. Accepted values:

      * `"regular"` — conversations that are not setup or mailbox type
      * `"setup"` — setup conversations
      * `"mailbox"` — mailbox-originated conversations
    </ParamField>

    <ParamField body="channel" type="string">
      Filter by the channel the conversation originated from. Accepted values:

      * `"phone"` — inbound phone calls
      * `"email"` — email conversations
      * `"app"` — mobile or native app
      * `"link"` — link or QR code
      * `"web"` — web widget (default fallback for unrecognized sources)
    </ParamField>

    <ParamField body="ownerId" type="string">
      Admin only. Filter conversations to genies owned by this user ID.
    </ParamField>
  </Expandable>
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "list",
    data: {
      agentIds: ["agent-uuid"],
      limit: 30,
      channel: "phone",
      conversationType: "regular",
    },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.helpgenie.ai/v1 \
    -H "Authorization: Bearer hg_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "resource": "conversations",
      "action": "list",
      "data": {
        "agentIds": ["agent-uuid"],
        "limit": 30,
        "channel": "phone",
        "conversationType": "regular"
      }
    }'
  ```
</CodeGroup>

### Response

<ResponseField name="conversations" type="Conversation[]">
  Array of conversation objects, each joined with basic genie info.

  <Expandable title="Conversation object">
    <ResponseField name="id" type="number">
      Unique conversation identifier.
    </ResponseField>

    <ResponseField name="agent_id" type="string | null">
      ID of the genie this conversation belongs to.
    </ResponseField>

    <ResponseField name="el_agent_id" type="string | null">
      External agent ID from the voice platform.
    </ResponseField>

    <ResponseField name="user_id" type="string | null">
      ID of the user who owns the genie.
    </ResponseField>

    <ResponseField name="status" type="string | null">
      Conversation status.
    </ResponseField>

    <ResponseField name="type" type="string | null">
      Conversation type.
    </ResponseField>

    <ResponseField name="metadata" type="object | null">
      Arbitrary metadata associated with the conversation.
    </ResponseField>

    <ResponseField name="viewed" type="boolean">
      Whether the conversation has been viewed.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 timestamp of when the conversation was created.
    </ResponseField>

    <ResponseField name="agents" type="object | null">
      Joined genie data.

      <Expandable title="properties">
        <ResponseField name="id" type="string">
          Genie ID.
        </ResponseField>

        <ResponseField name="name" type="string">
          Genie name.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="nextCursor" type="string | null">
  Opaque cursor string. Pass as `cursor` in the next request to fetch the next page. `null` when there are no more results.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  Whether more results are available beyond this page.
</ResponseField>

***

## Get conversation

Retrieves a single conversation by ID, including analysis details and associated media. The conversation is automatically marked as viewed on fetch. If analysis details exist but are incomplete, analysis runs automatically before the response is returned.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `get`
</ParamField>

<ParamField body="id" type="string" required>
  The conversation ID.
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "get",
    id: "123",
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.helpgenie.ai/v1/conversations \
    -H "Authorization: Bearer hg_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "action": "get",
      "id": "123"
    }'
  ```
</CodeGroup>

### Response

Returns the full conversation object spread directly into `data`, with nested genie, analysis details, and media.

<ResponseField name="id" type="string">
  Unique conversation identifier.
</ResponseField>

<ResponseField name="agent_id" type="string | null">
  ID of the genie this conversation belongs to.
</ResponseField>

<ResponseField name="status" type="string | null">
  Conversation status.
</ResponseField>

<ResponseField name="metadata" type="object | null">
  Arbitrary metadata associated with the conversation.
</ResponseField>

<ResponseField name="viewed" type="boolean">
  Whether the conversation has been viewed. Always `true` after a successful `get` call — the conversation is marked viewed automatically.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp.
</ResponseField>

<ResponseField name="agent" type="object | null">
  The genie that handled this conversation, including its full configuration and lead-info preset.
</ResponseField>

<ResponseField name="conversation_details" type="object[] | null">
  Analysis details for this conversation. Contains `summary`, `transcript`, `goals`, `topics`, `lead_info`, and `analysis_result`. If these fields were missing when the conversation was fetched, analysis is triggered automatically and the populated details are returned in this response.
</ResponseField>

<ResponseField name="medias" type="object[]">
  Media records (recordings, attachments) associated with this conversation. Empty array when no media exists.

  <Expandable title="item properties">
    <ResponseField name="id" type="string">Media record ID.</ResponseField>
    <ResponseField name="metadata" type="object">Media metadata, including `conversations_id`.</ResponseField>
  </Expandable>
</ResponseField>

***

## Sync conversations

Triggers a sync of conversations from the voice agent system for a specific genie.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `sync`
</ParamField>

<ParamField body="data" type="object" required>
  <Expandable title="properties">
    <ParamField body="agentId" type="string" required>
      The genie ID to sync conversations for. The user must own this genie.
    </ParamField>
  </Expandable>
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "sync",
    data: {
      agentId: "agent-uuid",
    },
  });
  ```
</CodeGroup>

### Response

<ResponseField name="success" type="boolean">
  `true` if the sync completed without errors.
</ResponseField>

<ResponseField name="synced" type="boolean">
  `true` if new conversation data was pulled from the voice agent system.
</ResponseField>

<ResponseField name="conversation" type="object">
  The synced conversation record with the latest data from the voice agent system.

  <Expandable title="properties">
    <ResponseField name="id" type="number">
      Unique conversation identifier.
    </ResponseField>

    <ResponseField name="agent_id" type="string">
      ID of the genie this conversation belongs to.
    </ResponseField>

    <ResponseField name="status" type="string">
      Updated conversation status from the voice platform.
    </ResponseField>

    <ResponseField name="metadata" type="object | null">
      Conversation metadata, including any data synced from the voice platform.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  Sync pulls the latest conversation data from the voice agent system, including updated transcripts, status, and metadata. The authenticated user must own the genie specified by `agentId`. A `403 FORBIDDEN` error is returned otherwise.
</Note>

***

## Analyze conversation

Runs an analysis on a specific conversation.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `analyze`
</ParamField>

<ParamField body="id" type="string" required>
  The conversation ID to analyze.
</ParamField>

<ParamField body="data" type="object">
  Additional parameters to pass to the analysis function.
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "analyze",
    id: "123",
    data: {
      // optional analysis parameters
    },
  });
  ```
</CodeGroup>

### Response

Returns a detailed analysis object generated by the `handle-conversation` edge function.

<ResponseField name="analysis" type="object">
  The analysis result for the conversation.

  <Expandable title="Analysis object">
    <ResponseField name="sentiment" type="string">
      Overall sentiment of the conversation. One of `positive`, `negative`, `neutral`, or `mixed`.
    </ResponseField>

    <ResponseField name="summary" type="string">
      A concise natural-language summary of the conversation.
    </ResponseField>

    <ResponseField name="key_topics" type="string[]">
      Array of topics discussed during the conversation.
    </ResponseField>

    <ResponseField name="action_items" type="object[]">
      Extracted action items or follow-ups.

      <Expandable title="ActionItem object">
        <ResponseField name="description" type="string">
          Description of the action item.
        </ResponseField>

        <ResponseField name="assignee" type="string | null">
          Who the action item is assigned to, if identifiable.
        </ResponseField>

        <ResponseField name="priority" type="string">
          Priority level: `high`, `medium`, or `low`.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="duration_analysis" type="object">
      Timing breakdown for the conversation.

      <Expandable title="properties">
        <ResponseField name="total_duration_seconds" type="number">
          Total duration of the conversation in seconds.
        </ResponseField>

        <ResponseField name="agent_talk_time_seconds" type="number">
          Time the genie spent speaking.
        </ResponseField>

        <ResponseField name="user_talk_time_seconds" type="number">
          Time the caller spent speaking.
        </ResponseField>

        <ResponseField name="silence_seconds" type="number">
          Total silence or dead air time.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="conversation_id" type="string">
      The ID of the analyzed conversation.
    </ResponseField>

    <ResponseField name="analyzed_at" type="string">
      ISO 8601 timestamp of when the analysis was performed.
    </ResponseField>
  </Expandable>
</ResponseField>

<Info>
  Analysis is performed asynchronously. For longer conversations, the response may take several seconds to return while the analysis is generated.
</Info>

***

## Update conversation

Updates metadata or fields on an existing conversation. Standard users can only update their own conversations.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `update`
</ParamField>

<ParamField body="id" type="string" required>
  The conversation ID to update.
</ParamField>

<ParamField body="data" type="object" required>
  Fields to update. Can be provided directly or nested under an `updates` key.
  Allowed fields: `agent_id`, `el_agent_id`, `metadata`, `status`, `type`, `user_id`, `viewed`.

  <Expandable title="properties">
    <ParamField body="status" type="string">
      Updated conversation status.
    </ParamField>

    <ParamField body="metadata" type="object">
      Updated metadata object.
    </ParamField>

    <ParamField body="viewed" type="boolean">
      Mark conversation as viewed or unviewed.
    </ParamField>
  </Expandable>
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "update",
    id: "123",
    data: {
      viewed: true,
      metadata: { notes: "Follow up required" },
    },
  });
  ```
</CodeGroup>

### Response

Returns the updated conversation object directly in `data`.

***

## Delete conversation

Permanently deletes a conversation. Standard users can only delete their own conversations. Admin users can delete any conversation.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `delete`
</ParamField>

<ParamField body="id" type="string" required>
  The conversation ID to delete.
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "delete",
    id: "123",
  });
  ```
</CodeGroup>

### Response

<ResponseField name="success" type="boolean">
  `true` if the conversation was deleted.
</ResponseField>

<ResponseField name="id" type="string">
  The ID of the deleted conversation.
</ResponseField>

<Warning>
  This action is permanent and cannot be undone.
</Warning>

***

## Mark all viewed

Marks all conversations as viewed for the authenticated user.

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `mark-all-viewed`
</ParamField>

<CodeGroup>
  ```typescript Request theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "mark-all-viewed",
  });
  ```
</CodeGroup>

### Response

<ResponseField name="success" type="boolean">
  `true` if the operation completed.
</ResponseField>

***

## Clear agent data

Permanently deletes all conversation history and activity records for a specific genie. Typically used when reassigning a genie to a different customer to ensure no prior data carries over.

<Warning>
  This action is irreversible and restricted to admin users. All conversations, inbox records, conversation details, and activity logs for the specified genie are permanently removed.
</Warning>

<ParamField body="resource" type="string" required>
  `conversations`
</ParamField>

<ParamField body="action" type="string" required>
  `clear-agent-data`
</ParamField>

<ParamField body="data" type="object" required>
  <Expandable title="properties">
    <ParamField body="agentId" type="string" required>
      The genie ID whose conversation history should be cleared.
    </ParamField>
  </Expandable>
</ParamField>

<ResponseField name="success" type="boolean">
  `true` if the operation completed successfully.
</ResponseField>

<ResponseField name="deletedConversations" type="number">
  The number of conversation records that were deleted.
</ResponseField>

<CodeGroup>
  ```typescript ApiService.invoke() theme={null}
  const response = await ApiService.invoke({
    resource: "conversations",
    action: "clear-agent-data",
    data: {
      agentId: "agent-uuid",
    },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.helpgenie.ai/v1/conversations \
    -H "Authorization: Bearer hg_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "resource": "conversations",
      "action": "clear-agent-data",
      "data": {
        "agentId": "agent-uuid"
      }
    }'
  ```

  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "success": true,
      "deletedConversations": 42
    }
  }
  ```
</CodeGroup>

***

## Error responses

| Status | Code               | Description                                    |
| ------ | ------------------ | ---------------------------------------------- |
| 400    | `VALIDATION_ERROR` | Missing required fields (e.g. conversation ID) |
| 403    | `FORBIDDEN`        | User does not own the genie (for sync)         |
| 404    | `NOT_FOUND`        | Conversation not found or access denied        |
| 500    | `INTERNAL_ERROR`   | Server error                                   |
