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

# List calls

> Page through your workspace's calls, newest first.

<Note>
  **Cursor pagination.** Pass the response's `next_cursor` back as `?cursor=` for the next page;
  `has_more` is `false` on the last page. Cursors are opaque — don't parse them. An invalid cursor
  returns `400 invalid_cursor`.
</Note>

<Tip>
  `transcript` is `null` in list items unless you pass `include=transcript`.
</Tip>


## OpenAPI

````yaml developers/openapi.json GET /v1/calls
openapi: 3.1.0
info:
  title: Vocily API
  description: >-
    Public REST API for placing outbound voice calls and reading their results.
    Authenticate with a workspace API key as a Bearer token.
  version: v1
servers:
  - url: https://api.vocily.com
    description: Production
security: []
paths:
  /v1/calls:
    get:
      tags:
        - calls
      summary: List calls
      description: >-
        List your workspace's calls, newest first, using cursor pagination.
        `transcript` is omitted from list items unless you pass
        `include=transcript`.
      operationId: list_calls_v1_calls_get
      parameters:
        - name: agent_id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Filter by agent id
            title: Agent Id
          description: Filter by agent id
        - name: status
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: 'Filter: started | completed | failed | …'
            title: Status
          description: 'Filter: started | completed | failed | …'
        - name: direction
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: 'Filter: inbound | outbound'
            title: Direction
          description: 'Filter: inbound | outbound'
        - name: date_from
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: 'null'
            description: started_at >= this datetime
            title: Date From
          description: started_at >= this datetime
        - name: date_to
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: 'null'
            description: started_at <= this datetime
            title: Date To
          description: started_at <= this datetime
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: >-
              Opaque cursor from a previous response's `next_cursor`; omit for
              the first page
            title: Cursor
          description: >-
            Opaque cursor from a previous response's `next_cursor`; omit for the
            first page
        - name: include
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: 'Comma-list of heavy fields to include. Currently: `transcript`'
            title: Include
          description: 'Comma-list of heavy fields to include. Currently: `transcript`'
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 100
            minimum: 1
            default: 20
            title: Limit
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Authorization
        - name: X-Vocily-Workspace
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: X-Vocily-Workspace
        - name: X-Vocily-Org
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: X-Vocily-Org
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicCallList'
              example:
                data:
                  - id: c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7
                    agent_id: 9b1c3d5e-7a90-4c21-8b6d-2e4f6a8c0d11
                    status: completed
                    direction: outbound
                    from_number: '+911171366867'
                    to_number: '+919876543210'
                    duration_seconds: 42
                    created_at: '2026-08-04T10:00:00.000Z'
                    connected_at: '2026-08-04T10:00:05.000Z'
                    ended_at: '2026-08-04T10:00:47.000Z'
                    metadata:
                      order_id: '88431'
                    variables:
                      customer_name: Rahul
                    cost:
                      currency: USD
                      total: 0.0554
                      rate_per_min: 0.0792
                    analysis:
                      sentiment: positive
                      outcome: booked
                      language: en
                      summary: Customer confirmed the appointment for Friday at 3pm.
                    custom_analysis:
                      lead_score: 9
                    transcript: null
                    recording_url: >-
                      https://api.vocily.com/v1/calls/c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7/recording
                has_more: true
                next_cursor: >-
                  eyJzIjoiMjAyNi0wOC0wNFQxMDowMDowMC4wMDBaIiwiaSI6ImM3YTFlMmIzIn0
        '400':
          description: The pagination cursor is invalid or expired.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: invalid_cursor
                message: The pagination cursor is invalid or expired.
        '401':
          description: Missing or invalid API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: unauthorized
                message: Missing or invalid API key.
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
        '429':
          description: Rate limit exceeded — honor Retry-After.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              example:
                code: rate_limited
                message: Rate limit exceeded — honor Retry-After.
      security:
        - bearerAuth: []
components:
  schemas:
    PublicCallList:
      properties:
        data:
          items:
            $ref: '#/components/schemas/PublicCallRead'
          type: array
          title: Data
        has_more:
          type: boolean
          title: Has More
        next_cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Next Cursor
      type: object
      required:
        - data
        - has_more
        - next_cursor
      title: PublicCallList
      description: >-
        Envelope for `GET /v1/calls`. Cursor pagination: pass `next_cursor` back
        as `?cursor=` for the

        next page; `has_more` is false on the last page. (A bare array can't
        carry paging metadata, and

        offset paging drifts under concurrent inserts — see
        `app/services/pagination.py`.)
    ApiError:
      type: object
      properties:
        code:
          type: string
          example: invalid_request
        message:
          type: string
          example: Malformed request parameter.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    PublicCallRead:
      properties:
        id:
          type: string
          title: Id
        agent_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Agent Id
        status:
          type: string
          title: Status
        direction:
          type: string
          title: Direction
        from_number:
          anyOf:
            - type: string
            - type: 'null'
          title: From Number
        to_number:
          anyOf:
            - type: string
            - type: 'null'
          title: To Number
        duration_seconds:
          anyOf:
            - type: integer
            - type: 'null'
          title: Duration Seconds
        created_at:
          type: string
          format: date-time
          title: Created At
        connected_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Connected At
        ended_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Ended At
        metadata:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Metadata
        variables:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Variables
        cost:
          anyOf:
            - $ref: '#/components/schemas/PublicCost'
            - type: 'null'
        analysis:
          anyOf:
            - $ref: '#/components/schemas/PublicAnalysis'
            - type: 'null'
        custom_analysis:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Custom Analysis
        transcript:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Transcript
        recording_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Recording Url
      type: object
      required:
        - id
        - agent_id
        - status
        - direction
        - from_number
        - to_number
        - duration_seconds
        - created_at
        - connected_at
        - ended_at
        - metadata
        - variables
        - cost
        - analysis
        - custom_analysis
        - transcript
        - recording_url
      title: PublicCallRead
      description: A call, as the public API promises it. Curated — see module docstring.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    PublicCost:
      properties:
        currency:
          type: string
          title: Currency
          default: USD
        total:
          type: number
          title: Total
        rate_per_min:
          anyOf:
            - type: number
            - type: 'null'
          title: Rate Per Min
      type: object
      required:
        - total
      title: PublicCost
      description: >-
        A call's cost, explicitly currency-labeled (the internal `cost_cents` is
        USD-wallet, so a bare

        number is ambiguous — this names the currency). `total` is in major
        units (USD dollars).
    PublicAnalysis:
      properties:
        sentiment:
          anyOf:
            - type: string
            - type: 'null'
          title: Sentiment
        outcome:
          anyOf:
            - type: string
            - type: 'null'
          title: Outcome
        language:
          anyOf:
            - type: string
            - type: 'null'
          title: Language
        summary:
          anyOf:
            - type: string
            - type: 'null'
          title: Summary
      type: object
      title: PublicAnalysis
      description: >-
        The platform AI analysis. **Same shape as the `call.analysis.completed`
        webhook** — see

        `app/webhooks/payload_builders.py::_analysis_object`; keep the two in
        lockstep.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Your API key as a Bearer token, e.g. `Authorization: Bearer vk_…`.'

````