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

# List lead outreach (all brands)

> Each lead's identity and `outreach` across every team in the enterprise: whether Avoca is still contacting the lead, and why outreach ended or never started. Same key rules and lead filters as `GET /api/v1/enterprise/{enterpriseId}/leads`, which is unchanged and does not return `outreach`. Keyset cursor-paginated ascending by `(created_at, id)`, except with an outreach window or `outreach_live`, which return rows in scan order (follow the cursor). Requires the `read:leads` permission.



## OpenAPI

````yaml /api-reference/openapi.json get /api/v1/enterprise/{enterpriseId}/leads/outreach
openapi: 3.1.0
info:
  title: Avoca Enterprise API
  description: >-
    Read-only programmatic access to Avoca data: calls and recordings,
    transcripts, leads, coach evaluations, Simple Scheduler sessions and
    analytics, outbound texting activity, enterprise support tickets, and
    customer survey results.
  version: 1.5.0
servers:
  - url: https://enterprise-api.avoca.ai
security:
  - bearerAuth: []
tags:
  - name: Calls
    description: Call records, recordings, transcripts, and pre-call transfers
  - name: Leads
    description: Unified leads (v0) and the canonical leads feed (v1)
  - name: Teams
    description: Teams accessible to the API key
  - name: Coach
    description: Coach (QA) call evaluations and rubrics
  - name: Scheduler Analytics (v0)
    description: Simple Scheduler analytics — legacy flat endpoints
  - name: Sessions & Bookings
    description: v1 scheduling-widget sessions and completed bookings
  - name: Analytics (v1)
    description: v1 funnel, UTM, service-area, and issue-type analytics
  - name: Outbound Texting
    description: Campaign text and subscription-event feeds for BI ingestion
  - name: Support Tickets
    description: Customer-safe enterprise support-ticket feed
  - name: Surveys
    description: >-
      Post-call customer survey results (CSAT, resolution, feedback) for BI
      ingestion
paths:
  /api/v1/enterprise/{enterpriseId}/leads/outreach:
    get:
      tags:
        - Leads
      summary: List lead outreach (all brands)
      description: >-
        Each lead's identity and `outreach` across every team in the enterprise:
        whether Avoca is still contacting the lead, and why outreach ended or
        never started. Same key rules and lead filters as `GET
        /api/v1/enterprise/{enterpriseId}/leads`, which is unchanged and does
        not return `outreach`. Keyset cursor-paginated ascending by
        `(created_at, id)`, except with an outreach window or `outreach_live`,
        which return rows in scan order (follow the cursor). Requires the
        `read:leads` permission.
      operationId: listEnterpriseLeadOutreach
      parameters:
        - name: enterpriseId
          in: path
          required: true
          description: The enterprise ID
          schema:
            type: integer
        - $ref: '#/components/parameters/leadsStartDate'
        - $ref: '#/components/parameters/leadsEndDate'
        - $ref: '#/components/parameters/leadsMedium'
        - $ref: '#/components/parameters/leadsSource'
        - $ref: '#/components/parameters/leadsStatus'
        - $ref: '#/components/parameters/leadsIncludeIgnored'
        - $ref: '#/components/parameters/leadsIncludeTestNumbers'
        - $ref: '#/components/parameters/leadsOutreachState'
        - $ref: '#/components/parameters/leadsOutreachLive'
        - $ref: '#/components/parameters/leadsOutreachChangedAfter'
        - $ref: '#/components/parameters/leadsOutreachChangedBefore'
        - $ref: '#/components/parameters/includeTestTeams'
        - $ref: '#/components/parameters/cursor'
        - $ref: '#/components/parameters/limit500default50'
      responses:
        '200':
          description: Paginated leads across all brands
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LeadOutreachRowV1'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
                  meta:
                    type: object
                    properties:
                      enterprise_id:
                        type: integer
                      team_ids:
                        type: array
                        items:
                          type: integer
                      as_of:
                        type: string
                        format: date-time
                        description: >-
                          Server time taken before this page's first read. Per
                          page, not per sweep.
                      outreach_changed_after:
                        type: string
                        format: date-time
                        description: >-
                          Effective outreach window lower bound. Present only
                          when the request used an outreach window.
                      outreach_changed_before:
                        type: string
                        format: date-time
                        description: >-
                          Effective outreach window upper bound (defaults to 2
                          minutes before the request). Pass it as the next
                          poll's `outreach_changed_after`. Present only when the
                          request used an outreach window.
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  parameters:
    leadsStartDate:
      name: start_date
      in: query
      description: Inclusive lower bound on `created_at` (>=)
      schema:
        type: string
        format: date-time
    leadsEndDate:
      name: end_date
      in: query
      description: Exclusive upper bound on `created_at` (<)
      schema:
        type: string
        format: date-time
    leadsMedium:
      name: medium
      in: query
      description: >-
        Lead-source medium. Every value of the lead-source medium enum is
        accepted.
      schema:
        type: string
        enum:
          - webhook
          - angi_webhook
          - email_alerts
          - st_bookings_alerts
          - st_native
          - hcp_native
          - google_lsa
          - yelp
          - thumbtack
          - web_chat
          - dropped_responder
          - genesys
          - everconnect
    leadsSource:
      name: source
      in: query
      description: Lead-source canonical `name` (exact match)
      schema:
        type: string
    leadsStatus:
      name: status
      in: query
      description: Lead processing status
      schema:
        type: string
        enum:
          - created
          - queued
          - processing
          - completed
          - failed
          - skipped
    leadsIncludeIgnored:
      name: include_ignored
      in: query
      description: >-
        When `true`, include suppressed leads (adds `is_ignored` /
        `ignored_reason`)
      schema:
        type: boolean
        default: false
    leadsIncludeTestNumbers:
      name: include_test_numbers
      in: query
      description: >-
        When `true`, include leads from the team's registered test phone numbers
        (default false)
      schema:
        type: boolean
        default: false
    leadsOutreachState:
      name: outreach_state
      in: query
      description: >-
        Comma-separated `outreach.state` values to return: `not_contacted`,
        `active`, `with_human`, `ended`. A filter only: it never changes the
        ordering. With `outreach_live` it may only list `active` and/or
        `with_human`.
      schema:
        type: string
        examples:
          - active,with_human
    leadsOutreachLive:
      name: outreach_live
      in: query
      description: >-
        When `true`, return every lead being worked right now (`active` or
        `with_human`) whose latest conversation had a message in the last 30
        days, instead of every lead. Rows come in no particular order; follow
        `pagination.cursor`, which is the only way to continue. A page can hold
        fewer than `limit` rows while `has_more` is true. Cannot be combined
        with `outreach_changed_after`.
      schema:
        type: boolean
        default: false
    leadsOutreachChangedAfter:
      name: outreach_changed_after
      in: query
      description: >-
        Inclusive lower bound on `outreach.changed_at`. Returns only the leads
        whose outreach changed in the window, each once, in no particular order;
        follow `pagination.cursor` (a page can hold fewer than `limit` rows
        while `has_more` is true). To poll, pass the previous response's
        `meta.outreach_changed_before`. A move to human follow-up or an
        AI-texting toggle without a message, a cleared opt-out, and a deleted
        conversation do not appear in windows. To pick them up, sweep
        `outreach_live=true` daily, and re-read with `ids` any lead you hold as
        `active` or `with_human` that the sweep did not return.
      schema:
        type: string
        format: date-time
    leadsOutreachChangedBefore:
      name: outreach_changed_before
      in: query
      description: >-
        Exclusive upper bound on `outreach.changed_at`. Requires
        `outreach_changed_after` and must be at most 24 hours after it. Defaults
        to 2 minutes before the request, so changes still being written land in
        the next window.
      schema:
        type: string
        format: date-time
    includeTestTeams:
      name: include_test_teams
      in: query
      description: >-
        Include designated internal QA/test teams in multi-team aggregations
        (default false)
      schema:
        type: boolean
        default: false
    cursor:
      name: cursor
      in: query
      description: >-
        Opaque pagination cursor from the previous response's
        `pagination.cursor`
      schema:
        type: string
    limit500default50:
      name: limit
      in: query
      description: Results per page (default 50, max 500)
      schema:
        type: integer
        default: 50
        maximum: 500
  schemas:
    LeadOutreachRowV1:
      type: object
      description: A lead's identity and outreach state. Join to the v1 leads feed on `id`.
      properties:
        id:
          type: integer
          description: The lead's id; the same `id` as the v1 leads feed.
          examples:
            - 9000001
        team_id:
          type: integer
          examples:
            - 70001
        external_id:
          type:
            - string
            - 'null'
        phone_number:
          type: string
          examples:
            - '+15555550100'
        created_at:
          type: string
          format: date-time
        is_partial:
          type: boolean
          description: >-
            True when a source behind `outreach` could not be read: `outreach`
            is then null, or its `last_outreach_at` is unknown. Read the lead
            again on the next request.
        outreach:
          type:
            - object
            - 'null'
          description: >-
            Where Avoca's outreach to the lead stands, read from the lead's
            latest text conversation. Null when its sources are temporarily
            unavailable (`is_partial` is then true).
          properties:
            state:
              type: string
              enum:
                - not_contacted
                - active
                - with_human
                - ended
              description: >-
                `not_contacted`: no text conversation was ever opened. `active`:
                the latest conversation is open and the AI is handling it.
                `with_human`: escalated, in human follow-up, or open with AI
                texting off. `ended`: opted out, or the latest conversation was
                resolved or closed.
            reason:
              type:
                - string
                - 'null'
              description: >-
                Set for `ended` (`opted_out`, `inactive`, `resolved_by_person`,
                `booked`, `resolved`, `closed_by_person`, `closed`) and
                `not_contacted` (`duplicate_lead`, `outreach_disabled`,
                `ignored`, `intake_failed`, `skipped`, `pending`,
                `phone_missing`, `enrolled_never_texted`, `no_campaign`); null
                otherwise. The set may grow.
              examples:
                - inactive
            is_idle:
              type:
                - boolean
                - 'null'
              description: >-
                `active` only: true when nothing has gone in or out for 72 hours
                or more. Null for other states. Computed at request time; it
                never moves `changed_at` or `updated_at`.
            changed_at:
              type: string
              format: date-time
              description: >-
                Latest of every timestamp behind the state: messages in or out,
                resolve, close, escalation, de-escalation, SMS opt-out changes,
                and intake settling. The outreach window filters on it.
            ended_at:
              type:
                - string
                - 'null'
              format: date-time
              description: '`ended` only: when outreach ended.'
            last_activity_at:
              type:
                - string
                - 'null'
              format: date-time
              description: Latest message in or out across the lead's conversations.
            last_outreach_at:
              type:
                - string
                - 'null'
              format: date-time
              description: Latest outbound text (AI or team member) or call attempt.
            last_customer_reply_at:
              type:
                - string
                - 'null'
              format: date-time
              description: Latest message from the lead.
          required:
            - state
            - reason
            - is_idle
            - changed_at
            - ended_at
            - last_activity_at
            - last_outreach_at
            - last_customer_reply_at
      required:
        - id
        - team_id
        - external_id
        - phone_number
        - created_at
        - is_partial
        - outreach
    CursorPagination:
      type: object
      properties:
        cursor:
          type:
            - string
            - 'null'
          description: >-
            Pass back as the `cursor` query parameter to fetch the next page;
            `null` on the last page
        has_more:
          type: boolean
        limit:
          type: integer
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error type
        message:
          type: string
          description: Human-readable description (newer endpoints)
      required:
        - error
  responses:
    Forbidden:
      description: API key lacks the required permission or team access
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key in the format `avoca_<64 hex characters>`

````