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

# Export Chat Sessions

> Returns chat sessions with their transcripts and tool calls, oldest first, as JSON or as Markdown ready to hand to Claude Code, claude.ai, a Codex agent or an MCP client.

**Enabled per account.** Ask Osvi support to turn it on; until then every call returns `403 feature_disabled`.

**Limits.** With no dates the export covers the last 24 hours, and one request covers at most 31 days. A window serves at most 1,000 sessions, 25 per page. Each token may make 10 requests a minute and 1,000 a day, and an account may run 2 exports at once. Every 429 carries a `Retry-After` header.

Pull your chat conversations, with every tool call the agent made, into Claude Code, claude.ai, a Codex agent or your own MCP client. Ask for JSON to process the data, or `format=markdown` to get one readable timeline per conversation, ready to hand to an LLM.

<Note>
  The export is enabled per account. Ask Osvi support to turn it on. Until then, every call returns `403 feature_disabled`.
</Note>

## Use it with Claude Code

```bash theme={null}
curl -s -H "API-Token: $OSVI_API_TOKEN" \
  "https://api.osvi.ai/v1/chat/export?format=markdown&per_page=25" \
  -o chats.md

claude "Read chats.md. Which tool calls failed, and what did the customer see when they did?"
```

With no dates, the export covers the **last 24 hours**. On claude.ai, attach the same file to a chat.

## Reading every page

Each response tells you exactly how to ask for the next one:

* **JSON:** send the parameters in `meta.next_page` as they are. It is `null` on the last page.
* **Markdown:** the `X-Next-Page` header holds the next page's query string, and the last line of the document repeats it.

`next_page` fixes the window to the timestamps page 1 used (`meta.range`). A window like "the last 24 hours" would otherwise move between requests and skip conversations. For the same reason, a request for page 2 or later without both `start_date` and `end_date` is rejected with `range_required`.

If you filter by `status` or `mode`, `next_page` also carries a `snapshot_token`. It keeps page boundaries stable while conversations close or change hands during your export.

## Limits

| Limit | Value |
| - | - |
| Window when no dates are sent | Last 24 hours |
| Longest window per request | 31 days. A bare date covers that whole day in IST |
| Conversations per window | 1,000. Past that, narrow the window: `422 records_cap_exceeded` |
| Conversations per page | 10 by default, 25 at most |
| Requests per token | 10 a minute and 1,000 a day (UTC) |
| Exports running at once | 2 per account. More returns `429 export_busy` |
| Time to build one page | 5 seconds. Longer returns `503 export_timeout` |

Every `429` carries a `Retry-After` header with the number of seconds to wait. Most HTTP clients and agent tools follow it automatically.

Each conversation is bounded so one very long chat can't crowd out the rest of the page:

* **Transcript:** 500 messages and 30,000 characters
* **Tool calls:** 500 events and 30,000 characters, counting tool names and IDs. Arguments over 4,000 characters are left out, outputs are cut at 8,000, and error messages at 2,000
* **Input and state fields:** 30,000 characters each

When a bound applies, the matching `*_truncated` flag is `true`, so you never mistake a cut-off record for a complete one.

## What's in a tool call

| Field | Meaning |
| - | - |
| `name`, `args` | The tool the agent called and the arguments it sent |
| `status` | `ok`, `error`, or `null` if no result was recorded (for example, the conversation ended mid-call) |
| `output` | What the tool returned to the agent |
| `error_message` | Why it failed, when `status` is `error`. `error_message_truncated` is `true` if it was cut short |
| `duration_ms` | How long the tool took |

Knowledge-base lookups and the internal events behind buttons, carousels and date pickers are not listed as tool calls. Interactive prompts and replies show up in the transcript with `type: "interaction"`.


## OpenAPI

````yaml GET /v1/chat/export
openapi: 3.1.0
info:
  title: OSVI AI API
  description: REST API for the OSVI AI voice and chat platform
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.osvi.ai
security:
  - ApiToken: []
paths:
  /v1/chat/export:
    get:
      summary: Export chat sessions
      description: >-
        Returns chat sessions with their transcripts and tool calls, oldest
        first, as JSON or as Markdown ready to hand to Claude Code, claude.ai, a
        Codex agent or an MCP client.


        **Enabled per account.** Ask Osvi support to turn it on; until then
        every call returns `403 feature_disabled`.


        **Limits.** With no dates the export covers the last 24 hours, and one
        request covers at most 31 days. A window serves at most 1,000 sessions,
        25 per page. Each token may make 10 requests a minute and 1,000 a day,
        and an account may run 2 exports at once. Every 429 carries a
        `Retry-After` header.
      parameters:
        - name: start_date
          in: query
          required: false
          description: >-
            Start of the window. A date (`2026-10-09`, the whole day in IST) or
            an ISO 8601 timestamp. Defaults to 24 hours before `end_date`.
            Required, with `end_date`, on pages after the first: copy both from
            `meta.next_page`.
          schema:
            type: string
          example: '2026-10-09'
        - name: end_date
          in: query
          required: false
          description: >-
            End of the window, same formats. Defaults to now. The window may
            span at most 31 days.
          schema:
            type: string
          example: '2026-10-09'
        - name: page
          in: query
          required: false
          description: >-
            Page number. Follow `meta.next_page` rather than counting pages
            yourself.
          schema:
            type: integer
            default: 1
          example: 1
        - name: per_page
          in: query
          required: false
          description: Sessions per page (max 25).
          schema:
            type: integer
            default: 10
            maximum: 25
          example: 25
        - name: format
          in: query
          required: false
          description: >-
            `json`, or `markdown` for one readable timeline per session. The
            `.md` path suffix works too.
          schema:
            type: string
            enum:
              - json
              - markdown
            default: json
          example: markdown
        - name: status
          in: query
          required: false
          description: Only sessions with these statuses. Accepts a comma-separated list.
          schema:
            type: string
          example: closed
        - name: mode
          in: query
          required: false
          description: >-
            Only sessions in this mode. `support` means an operator has taken
            over.
          schema:
            type: string
            enum:
              - ai
              - support
          example: ai
        - name: agent_uuid
          in: query
          required: false
          description: >-
            Only sessions handled by this chat agent. Returns `404` if the agent
            is not on your account.
          schema:
            type: string
          example: agent_Xk2pQ9rT
        - name: customer_id
          in: query
          required: false
          description: Only one customer's sessions.
          schema:
            type: string
          example: '+919812345678'
        - name: snapshot_token
          in: query
          required: false
          description: >-
            Keeps page boundaries stable while sessions change status or mode.
            Comes back in `meta` when `status` or `mode` is filtered, and is
            already included in `meta.next_page`.
          schema:
            type: string
      responses:
        '200':
          description: >-
            One page of sessions. In Markdown, pagination comes back in the
            `X-Total-Count`, `X-Current-Page`, `X-Total-Pages`, `X-Per-Page`,
            `X-Records-Cap`, `X-Capped`, `X-Range-Start`, `X-Range-End`,
            `X-Next-Page` (a query string) and `X-Snapshot-Token` headers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ChatExportSession'
                  meta:
                    $ref: '#/components/schemas/ChatExportMeta'
            text/markdown:
              schema:
                type: string
              example: >
                # Chat export: 2026-10-11 10:30:00 UTC to 2026-10-12 10:30:00
                UTC

                Page 1 of 9, 212 sessions in this window.


                ---


                ## Session 8f3c2a1e-5b7d-4c9a-9e21-6d0f4b2a7c13

                - Agent: Order Support (agent_Xk2pQ9rT)

                - Customer: +919812345678

                - Status: closed | Mode: ai | State: resolution

                - Started: 2026-10-09 10:02:11 UTC | Last message: 2026-10-09
                10:04:52 UTC

                - Messages: 4 | Tool calls: 1


                **User** (10:02:11)

                Where is my order ORD-5521?


                > Tool call: lookup_order (ok, 184 ms, 10:02:13)

                > args: {"order_id":"ORD-5521"}

                > output: {"status":"shipped","eta":"2026-10-11"}


                **Assistant** (10:02:15)

                It shipped yesterday and should arrive Friday.


                ---


                _Next page: request again with
                end_date=2026-10-12T10%3A30%3A00Z&format=markdown&page=2&per_page=25&start_date=2026-10-11T10%3A30%3A00Z_
        '401':
          description: Invalid or missing API token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorUnauthorized'
        '403':
          description: The export is not enabled for this account.
          content:
            application/json:
              examples:
                feature_disabled:
                  summary: Not enabled
                  value:
                    success: false
                    error: feature_disabled
                    feature: chat_export_api
                    message: >-
                      Feature disabled: Public chat export API (GET
                      /v1/chat/export).
        '404':
          description: The `agent_uuid` filter does not match an agent on your account.
          content:
            application/json:
              examples:
                agent_not_found:
                  summary: Unknown agent
                  value:
                    success: false
                    error: agent_not_found
                    details: null
        '422':
          description: >-
            The request can't be served as asked. `details.message` says what to
            change.
          content:
            application/json:
              examples:
                date_range_too_long:
                  summary: Window longer than 31 days
                  value:
                    success: false
                    error: date_range_too_long
                    details:
                      max_days: 31
                      message: >-
                        A single export can cover at most 31 days. Split the
                        range into smaller windows.
                range_required:
                  summary: Later page without dates
                  value:
                    success: false
                    error: range_required
                    details:
                      message: >-
                        Pages after the first need the start_date and end_date
                        from meta.next_page, so the window doesn't move between
                        pages.
                invalid_date_range:
                  summary: Unreadable date, or end before start
                  value:
                    success: false
                    error: invalid_date_range
                    details:
                      message: end_date is before start_date.
                records_cap_exceeded:
                  summary: Past the 1,000-session cap
                  value:
                    success: false
                    error: records_cap_exceeded
                    details:
                      records_cap: 1000
                      message: >-
                        This export serves at most 1000 records per request
                        window — narrow the date range or filters to page
                        through the rest.
                snapshot_expired:
                  summary: Snapshot expired mid-walk
                  value:
                    success: false
                    error: snapshot_expired
                    details:
                      message: >-
                        This export snapshot has expired, was not found, or no
                        longer matches the requested filters — restart
                        pagination from page 1 without snapshot_token.
                unsupported_format:
                  summary: Unknown format
                  value:
                    success: false
                    error: unsupported_format
                    details:
                      message: format must be json or markdown.
        '429':
          description: >-
            Too many requests. Wait for the number of seconds in the
            `Retry-After` header, then retry.
          content:
            application/json:
              examples:
                rate_limited:
                  summary: Per-minute or daily limit
                  value:
                    success: false
                    error: Rate limit exceeded. Please try again later.
                    details:
                      retry_after: 23
                export_busy:
                  summary: Two exports already running
                  value:
                    success: false
                    error: export_busy
                    details:
                      retry_after: 5
                      message: >-
                        Another export for this account is still running. Wait
                        and retry, one request at a time.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
        '503':
          description: The page took longer than 5 seconds to build.
          content:
            application/json:
              examples:
                export_timeout:
                  summary: Timed out
                  value:
                    success: false
                    error: export_timeout
                    details:
                      message: >-
                        This page took too long to build. Use a smaller per_page
                        or a shorter date range.
components:
  schemas:
    ChatExportSession:
      type: object
      description: >-
        One chat session. Large fields are bounded per session; each
        `*_truncated` flag says when a bound applied.
      properties:
        session_id:
          type: string
          format: uuid
          example: 8f3c2a1e-5b7d-4c9a-9e21-6d0f4b2a7c13
        customer_id:
          type: string
          example: '+919812345678'
        customer_id_truncated:
          type: boolean
          example: false
        agent:
          type: object
          properties:
            uuid:
              type: string
              example: agent_Xk2pQ9rT
            name:
              type: string
              example: Order Support
        mode:
          type: string
          enum:
            - ai
            - support
          description: '`support` while an operator has taken over.'
          example: ai
        status:
          type: string
          enum:
            - active
            - closed
            - dormant
          example: closed
        current_state:
          type: string
          nullable: true
          example: resolution
        current_state_truncated:
          type: boolean
          example: false
        help_requested:
          type: boolean
          example: false
        created_at:
          type: string
          format: date-time
          example: '2026-10-09T10:02:11Z'
        last_message_at:
          type: string
          format: date-time
          nullable: true
          example: '2026-10-09T10:04:52Z'
        message_count:
          type: integer
          example: 4
        user_message_count:
          type: integer
          example: 2
        assistant_message_count:
          type: integer
          example: 2
        input_fields:
          type: object
          nullable: true
          description: >-
            `null` when larger than 30,000 characters (see
            `metadata_truncated`).
          example:
            name: Riya
        state_fields:
          type: object
          nullable: true
          example:
            order_id: ORD-5521
        metadata_truncated:
          type: boolean
          example: false
        transcript:
          type: array
          description: >-
            Messages in order. At most 500 messages and 30,000 characters per
            session.
          items:
            $ref: '#/components/schemas/ChatExportMessage'
        transcript_truncated:
          type: boolean
          example: false
        tool_calls:
          type: array
          description: >-
            Tool calls in order. At most 500 events and 30,000 characters per
            session.
          items:
            $ref: '#/components/schemas/ChatExportToolCall'
        tool_calls_truncated:
          type: boolean
          example: false
    ChatExportMeta:
      type: object
      properties:
        current_page:
          type: integer
          example: 1
        total_pages:
          type: integer
          description: Pages you can reach under `records_cap`.
          example: 9
        total_count:
          type: integer
          description: Sessions matching the window and filters, before the cap.
          example: 212
        per_page:
          type: integer
          example: 25
        records_cap:
          type: integer
          example: 1000
        capped:
          type: boolean
          description: >-
            `true` when the window holds more sessions than the export serves.
            Narrow the window to read the rest.
          example: false
        snapshot_token:
          type: string
          nullable: true
          description: >-
            Only when `status` or `mode` is filtered. Already included in
            `next_page`.
          example: c2e1f0a4b7d94e3a
        snapshot_restarted:
          type: boolean
          description: Only when `status` or `mode` is filtered.
          example: false
        range:
          type: object
          properties:
            start:
              type: string
              format: date-time
              example: '2026-10-11T10:30:00Z'
            end:
              type: string
              format: date-time
              example: '2026-10-12T10:30:00Z'
            defaulted:
              type: boolean
              description: '`true` when a date was missing and the default window was used.'
              example: true
            max_days:
              type: integer
              example: 31
        next_page:
          type: object
          nullable: true
          description: >-
            Query parameters for the next page, with the window fixed to this
            page's `range`. Send them as-is. `null` on the last page.
          example:
            page: 2
            per_page: 25
            start_date: '2026-10-11T10:30:00Z'
            end_date: '2026-10-12T10:30:00Z'
    ErrorUnauthorized:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: Invalid API token
    ChatExportMessage:
      type: object
      properties:
        role:
          type: string
          example: user
        content:
          type: string
          example: Where is my order ORD-5521?
        created_at:
          type: string
          format: date-time
          example: '2026-10-09T10:02:11.087Z'
        type:
          type: string
          enum:
            - message
            - interaction
          description: '`interaction` for a button, carousel or date-picker prompt or reply.'
          example: message
    ChatExportToolCall:
      type: object
      description: One tool call the agent made during the session, paired with its result.
      properties:
        request_id:
          type: string
          nullable: true
          description: The model's tool-call id; links the call to its result.
          example: call_7Hq2
        name:
          type: string
          nullable: true
          example: lookup_order
        called_at:
          type: string
          format: date-time
          description: When the call was made, in UTC with milliseconds.
          example: '2026-10-09T10:02:13.412Z'
        args:
          type: object
          nullable: true
          description: >-
            Arguments the agent sent. `null` when they exceeded 4,000 characters
            (see `args_truncated`) or when only the result was recorded.
          example:
            order_id: ORD-5521
        args_truncated:
          type: boolean
          example: false
        status:
          type: string
          nullable: true
          enum:
            - ok
            - error
            - null
          description: >-
            `null` when no result was recorded, for example when the session
            ended mid-call.
          example: ok
        output:
          type: string
          nullable: true
          description: What the tool returned to the agent, clipped to 8,000 characters.
          example: '{"status":"shipped","eta":"2026-10-11"}'
        output_truncated:
          type: boolean
          example: false
        error_message:
          type: string
          nullable: true
          description: Why the call failed, clipped to 2,000 characters.
          example: null
        error_message_truncated:
          type: boolean
          example: false
        duration_ms:
          type: integer
          nullable: true
          example: 184
  securitySchemes:
    ApiToken:
      type: apiKey
      in: header
      name: API-Token
      description: >-
        16-character API token associated with your OSVI account. Find it in
        your dashboard under Settings → API.

````

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