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

# List meetings

> **Credential:** user token · **Role:** any (`read`)



## OpenAPI

````yaml /openapi/v1.json get /v1/meetings
openapi: 3.1.0
info:
  title: Peeve API
  version: '2026-08-17'
  description: >-
    The `/v1` API. Server-to-server only — no CORS headers are sent, no `Origin`
    is checked, and publishable keys are rejected everywhere.


    Most endpoints take a **user token** (`pv_ut_…`), which carries its owner's
    live workspace role. `/v1/users` and `/v1/answer` take the **workspace
    secret key** (`sk_…`). The credential and the required role are stated on
    every operation — they are not uniform.
servers:
  - url: https://api.peeve.ai
security:
  - userToken: []
tags:
  - name: Sessions
    description: Agent conversations and their transcripts.
  - name: Contacts
    description: >-
      Everyone Peeve knows about: **users** your product identified, and
      anonymous **visitors**. Filter with `?kind=`.
  - name: Users
    description: Push your identified users into Peeve from your backend.
  - name: Ask
    description: Ask the agent a question from your backend and get a grounded answer.
  - name: Leads
    description: >-
      Visitors the agent qualified. Read and re-status only — capture happens
      through Peeve's own channels.
  - name: Meetings
    description: Meetings booked through the agent.
  - name: Hand-offs
    description: Escalations to a human, and their status.
  - name: Analytics
    description: Usage and satisfaction results.
  - name: Configuration
    description: Guardrails and the kill switch.
  - name: Webhooks
    description: >-
      Register and manage the endpoints Peeve delivers events to. Equivalent to
      the Connectors UI — an endpoint created here is the same row, with the
      same guarantees.
paths:
  /v1/meetings:
    get:
      tags:
        - Meetings
      summary: List meetings
      description: '**Credential:** user token · **Role:** any (`read`)'
      operationId: listMeetings
      parameters:
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/cursor'
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - created_at
            default: created_at
        - $ref: '#/components/parameters/order'
        - $ref: '#/components/parameters/created_after'
        - $ref: '#/components/parameters/created_before'
        - name: status
          in: query
          schema:
            type: string
            enum:
              - scheduled
              - completed
              - canceled
              - no_show
        - name: provider
          in: query
          schema:
            type: string
            enum:
              - calcom
              - calendly
              - other
        - name: contact_id
          in: query
          schema:
            type: string
            format: uuid
        - name: session_id
          in: query
          schema:
            type: string
            format: uuid
        - name: lead_id
          in: query
          schema:
            type: string
            format: uuid
        - name: starts_after
          in: query
          schema:
            type: string
            format: date-time
        - name: starts_before
          in: query
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: A page of meetings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeetingList'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    limit:
      name: limit
      in: query
      schema:
        type: integer
        default: 50
        maximum: 200
        minimum: 1
      description: Page size. Over 200 is a `400`, not a silent clamp.
    cursor:
      name: cursor
      in: query
      schema:
        type: string
      description: >-
        An opaque `next_cursor` from a previous page. Do not parse or construct
        it. Reusing a cursor under a different `sort`/`order` is rejected.
    order:
      name: order
      in: query
      schema:
        type: string
        enum:
          - asc
          - desc
        default: desc
    created_after:
      name: created_after
      in: query
      schema:
        type: string
        format: date-time
    created_before:
      name: created_before
      in: query
      schema:
        type: string
        format: date-time
  schemas:
    MeetingList:
      allOf:
        - $ref: '#/components/schemas/ListEnvelope'
        - type: object
          properties:
            data:
              type: array
              items:
                $ref: '#/components/schemas/Meeting'
    ListEnvelope:
      type: object
      required:
        - object
        - data
        - has_more
        - next_cursor
        - request_id
      properties:
        object:
          type: string
          const: list
        data:
          type: array
          items:
            type: object
            additionalProperties: true
        has_more:
          type: boolean
          description: Always present, so a paging loop never branches.
        next_cursor:
          type:
            - string
            - 'null'
          description: Pass as `cursor` for the next page. `null` on the last page.
        request_id:
          type: string
    Meeting:
      type: object
      properties:
        id:
          type: string
          format: uuid
        object:
          type: string
          const: meeting
        provider:
          type: string
          enum:
            - calcom
            - calendly
            - other
        external_ref:
          type:
            - string
            - 'null'
        contact_id:
          type:
            - string
            - 'null'
          format: uuid
        session_id:
          type:
            - string
            - 'null'
          format: uuid
        handoff_id:
          type:
            - string
            - 'null'
          format: uuid
        lead_id:
          type:
            - string
            - 'null'
          format: uuid
          description: Present only when the booking came from the sales flow.
        event_type:
          type:
            - string
            - 'null'
        title:
          type:
            - string
            - 'null'
        start_at:
          type:
            - string
            - 'null'
          format: date-time
        end_at:
          type:
            - string
            - 'null'
          format: date-time
        timezone:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - scheduled
            - completed
            - canceled
            - no_show
        attendee_name:
          type:
            - string
            - 'null'
        attendee_email:
          type:
            - string
            - 'null'
        join_url:
          type:
            - string
            - 'null'
        qualification:
          type:
            - object
            - 'null'
          additionalProperties: true
          description: What the agent established before booking.
        created_at:
          type: string
          format: date-time
    ErrorEnvelope:
      type: object
      required:
        - error
        - request_id
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
          properties:
            type:
              type: string
              enum:
                - authentication_error
                - invalid_request_error
                - not_found_error
                - rate_limit_error
                - api_error
              description: The coarse family. Branch on this.
            code:
              type: string
              description: The stable machine label.
            message:
              type: string
            param:
              type: string
              description: The offending query parameter or dotted body path.
        request_id:
          type: string
  responses:
    BadRequest:
      description: >-
        An unknown or duplicated parameter, a bad value, a backwards date
        window, or a rejected unknown body key. The `param` field names the
        offender.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              type: invalid_request_error
              code: unknown_parameter
              message: >-
                Unknown query parameter 'since'. This endpoint accepts:
                created_after, created_before, cursor, limit, order, sort.
              param: since
            request_id: req_xxx
    Unauthorized:
      description: >-
        Missing, invalid or revoked credential — or the wrong **kind** of
        credential.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          examples:
            wrongKind:
              summary: A secret key on a user-token endpoint
              value:
                error:
                  type: authentication_error
                  code: user_token_required
                  message: >-
                    This endpoint requires a user token (pv_ut_…), not a
                    workspace secret key. A shared key cannot express a person's
                    role, so it cannot be used to read workspace data or change
                    configuration. Create your own token in Settings → API keys.
                request_id: req_xxx
            publishable:
              summary: A publishable key
              value:
                error:
                  type: authentication_error
                  code: publishable_key_not_allowed
                  message: >-
                    Publishable keys (pk_…) are public by construction and can
                    never read or write workspace data.
                request_id: req_xxx
            invalid:
              summary: Revoked, unknown, or the owner left the workspace
              value:
                error:
                  type: authentication_error
                  code: invalid_credential
                  message: >-
                    That credential is not valid, has been revoked, or its owner
                    is no longer a member of this workspace.
                request_id: req_xxx
    RateLimited:
      description: >-
        Over the per-credential ceiling. Carries `Retry-After`. All `/v1`
        endpoints share one bucket per credential.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              type: rate_limit_error
              code: rate_limit_exceeded
              message: Too many requests (key limit). Retry in 60s.
            request_id: req_xxx
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait.
  securitySchemes:
    userToken:
      type: http
      scheme: bearer
      description: >-
        A user token (`pv_ut_…`) as `Authorization: Bearer pv_ut_…`.
        `X-Peeve-Key` is accepted too. **Never a query parameter** — URLs end up
        in proxy logs and `Referer` headers.


        The token carries its owner's **live** workspace role, re-read on every
        call.

````