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

# The conversation with one lead



## OpenAPI

````yaml https://app.reclosed.io/api-docs/reclosed-openapi.yaml get /campaigns/{campaignId}/leads/{leadId}/messages
openapi: 3.1.0
info:
  title: Reclosed API
  version: 1.0.0
  description: >
    A read-only HTTP API for reading your Reclosed data from your own systems.


    Every endpoint is a GET, authenticated with an API key you generate yourself
    on the API keys

    page in Reclosed. Six endpoints, one credential, one response shape.


    **Branch on `error.code`, not on the HTTP status or the message.** The code
    is the part we

    promise not to change. Under `/v1` we may add fields; we will not rename or
    remove them, and we

    will not change what an existing field means. Write your integration to
    ignore fields it does not

    recognise and it will keep working.
  contact:
    name: Reclosed
servers:
  - url: https://api-production-a5d3.up.railway.app/v1
    description: production
security:
  - apiKey: []
tags:
  - name: Campaigns
  - name: Compliance
paths:
  /campaigns/{campaignId}/leads/{leadId}/messages:
    get:
      tags:
        - Campaigns
      summary: The conversation with one lead
      operationId: listLeadMessages
      parameters:
        - $ref: '#/components/parameters/CampaignId'
        - name: leadId
          in: path
          required: true
          schema:
            type: string
          description: The lead id.
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Cursor'
      responses:
        '200':
          description: A page of messages, oldest first.
          content:
            application/json:
              schema:
                allOf:
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/Message'
                    required:
                      - data
                  - $ref: '#/components/schemas/Paged'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: >
            No such campaign or lead, **or** it is not yours — the two are
            deliberately

            indistinguishable, so that an id cannot be probed for existence.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          $ref: '#/components/responses/ResultTooLarge'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/Unavailable'
components:
  parameters:
    CampaignId:
      name: campaignId
      in: path
      required: true
      schema:
        type: string
      description: The campaign id.
    Limit:
      name: limit
      in: query
      required: false
      schema:
        type: integer
        minimum: 1
        maximum: 200
        default: 50
      description: Page size. An oversized value is clamped rather than rejected.
    Cursor:
      name: cursor
      in: query
      required: false
      schema:
        type: string
      description: Pass `pagination.nextCursor` from the previous page.
  schemas:
    Message:
      type: object
      properties:
        id:
          type: string
        direction:
          type: string
          enum:
            - inbound
            - outbound
        body:
          type: string
        stage:
          type: string
          description: Absent for stage 0.
        sentAtMs:
          type: integer
          description: Epoch milliseconds.
        channel:
          type: string
          description: e.g. sms, whatsapp, imessage.
        delivery:
          type:
            - object
            - 'null'
          description: Outbound only — an inbound message has no delivery leg.
          properties:
            status:
              type: string
            providerStatus:
              type:
                - string
                - 'null'
            errorDetail:
              type:
                - string
                - 'null'
    Paged:
      type: object
      properties:
        pagination:
          type: object
          properties:
            limit:
              type: integer
            total:
              type: integer
              description: Total rows across all pages.
            hasMore:
              type: boolean
            nextCursor:
              type:
                - string
                - 'null'
              description: Pass to `cursor` for the next page. Null on the last page.
          required:
            - limit
            - total
            - hasMore
            - nextCursor
      required:
        - pagination
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: The stable part — branch on this.
              enum:
                - unauthorized
                - forbidden
                - not_found
                - invalid_params
                - rate_limited
                - result_too_large
                - unavailable
                - internal_error
            message:
              type: string
              description: For a human reading a log. Not stable.
            traceId:
              type: string
              description: Quote this in a support request.
          required:
            - code
            - message
            - traceId
      required:
        - error
  responses:
    Unauthorized:
      description: 'Missing or invalid key. Carries `WWW-Authenticate: Bearer`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ResultTooLarge:
      description: Too many rows to scan. Narrow the request rather than retrying it.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: >
        Too many requests. Carries `Retry-After` in seconds. 600/min per key,
        and separately 600/min

        per source IP — several keys on one host share the IP budget.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unavailable:
      description: >
        We could not verify your key — the key store was unreachable. Retry with
        backoff; the key is

        fine.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >
        `Authorization: Bearer rk_live_…`. Keys do not expire and are scoped to
        one account. The

        secret is shown once at creation and stored only as a hash, so it cannot
        be recovered — if

        you lose it, revoke it and generate another on the API keys page.

````

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