Avoca Leads API

Unified leads (v0) and the canonical leads feed (v1)

OpenAPI Specification

avoca-leads-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Avoca Enterprise Analytics (v1) Analytics (v1) Leads API
  description: 'Read-only programmatic access to Avoca data: calls, transcripts, leads, coach evaluations, Simple Scheduler sessions and analytics, and outbound texting activity.'
  version: 1.3.0
servers:
- url: https://enterprise-api.avoca.ai
security:
- bearerAuth: []
tags:
- name: Leads
  description: Unified leads (v0) and the canonical leads feed (v1)
paths:
  /api/leads:
    get:
      tags:
      - Leads
      summary: List unified leads (v0)
      description: Channel-touchpoint aggregation of leads across calls, the scheduling widget, web chat, text, and Google LSA. This is **not** the canonical leads record and does not include the raw third-party payload — for that, use the v1 leads feed (`GET /api/v1/teams/{teamId}/leads`). Requires the `read:leads` permission.
      operationId: listLeadsV0
      parameters:
      - $ref: '#/components/parameters/xTeamId'
      - $ref: '#/components/parameters/startDate7d'
      - $ref: '#/components/parameters/endDateNow'
      - name: type
        in: query
        description: Filter by lead type
        schema:
          type: string
          enum:
          - call
          - scheduling_widget
          - web_chat
          - text
          - google_lsa
      - $ref: '#/components/parameters/limit1000'
      - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: Paginated list of unified leads
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LeadV0'
                  pagination:
                    $ref: '#/components/schemas/OffsetPagination'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/teams/{teamId}/leads:
    get:
      tags:
      - Leads
      summary: List leads (single team)
      description: 'The canonical leads feed for one team: the historical/pull counterpart to the `lead.*` event webhooks, including the raw third-party payload. Keyset cursor-paginated ascending by `(created_at, id)`. Leads from registered test phone numbers are excluded by default (`include_test_numbers=true` opts in). Requires the `read:leads` permission.'
      operationId: listTeamLeads
      parameters:
      - $ref: '#/components/parameters/teamIdPath'
      - $ref: '#/components/parameters/leadsStartDate'
      - $ref: '#/components/parameters/leadsEndDate'
      - $ref: '#/components/parameters/leadsMedium'
      - $ref: '#/components/parameters/leadsSource'
      - $ref: '#/components/parameters/leadsStatus'
      - $ref: '#/components/parameters/leadsIncludeRaw'
      - $ref: '#/components/parameters/leadsIncludeIgnored'
      - $ref: '#/components/parameters/leadsIncludeTestNumbers'
      - $ref: '#/components/parameters/cursor'
      - $ref: '#/components/parameters/limit500default50'
      responses:
        '200':
          description: Paginated leads
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LeadV1'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
                  meta:
                    $ref: '#/components/schemas/TeamMeta'
        '403':
          $ref: '#/components/responses/Forbidden'
  /api/v1/enterprise/{enterpriseId}/leads:
    get:
      tags:
      - Leads
      summary: List leads (all brands)
      description: The canonical leads feed across every team (brand) in the enterprise. Requires an `enterprise_all_teams` key whose enterprise matches the path — single-team and portfolio keys receive 403. Every row carries `team_id`. Same query parameters as the single-team feed. Requires the `read:leads` permission.
      operationId: listEnterpriseLeads
      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/leadsIncludeRaw'
      - $ref: '#/components/parameters/leadsIncludeIgnored'
      - $ref: '#/components/parameters/leadsIncludeTestNumbers'
      - $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/LeadV1'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
                  meta:
                    type: object
                    properties:
                      enterprise_id:
                        type: integer
                      team_ids:
                        type: array
                        items:
                          type: integer
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  parameters:
    limit500default50:
      name: limit
      in: query
      description: Results per page (default 50, max 500)
      schema:
        type: integer
        default: 50
        maximum: 500
    leadsIncludeIgnored:
      name: include_ignored
      in: query
      description: When `true`, include suppressed leads (adds `is_ignored` / `ignored_reason`)
      schema:
        type: boolean
        default: false
    leadsStatus:
      name: status
      in: query
      description: Lead processing status
      schema:
        type: string
        enum:
        - created
        - queued
        - processing
        - completed
        - failed
        - skipped
    leadsSource:
      name: source
      in: query
      description: Lead-source canonical `name` (exact match)
      schema:
        type: string
    offset:
      name: offset
      in: query
      description: Pagination offset (default 0)
      schema:
        type: integer
        default: 0
    leadsStartDate:
      name: start_date
      in: query
      description: Inclusive lower bound on `created_at` (>=)
      schema:
        type: string
        format: date-time
    teamIdPath:
      name: teamId
      in: path
      required: true
      description: The team ID
      schema:
        type: integer
    leadsMedium:
      name: medium
      in: query
      description: Lead-source medium
      schema:
        type: string
        enum:
        - webhook
        - email_alerts
        - st_bookings_alerts
        - st_native
        - google_lsa
        - yelp
        - web_chat
        - dropped_responder
    leadsEndDate:
      name: end_date
      in: query
      description: Exclusive upper bound on `created_at` (<)
      schema:
        type: string
        format: date-time
    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
    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
    leadsIncludeRaw:
      name: include_raw
      in: query
      description: When `false`, omit the `raw` third-party payload field (default true)
      schema:
        type: boolean
        default: true
    xTeamId:
      name: x-team-id
      in: header
      description: Target team ID. Required for multi-team (`enterprise_all_teams` / `portfolio_all_teams`) keys on v0 endpoints; single-team keys are locked to their team and omit it.
      schema:
        type: integer
    limit1000:
      name: limit
      in: query
      description: Results per page (default 100, max 1000)
      schema:
        type: integer
        default: 100
        maximum: 1000
    endDateNow:
      name: end_date
      in: query
      description: End of date range (ISO 8601; default now)
      schema:
        type: string
        format: date-time
    cursor:
      name: cursor
      in: query
      description: Opaque pagination cursor from the previous response's `pagination.cursor`
      schema:
        type: string
    startDate7d:
      name: start_date
      in: query
      description: Start of date range (ISO 8601; default 7 days ago)
      schema:
        type: string
        format: date-time
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error type
        message:
          type: string
          description: Human-readable description (newer endpoints)
      required:
      - error
    OffsetPagination:
      type: object
      properties:
        limit:
          type: integer
        offset:
          type: integer
        has_more:
          type: boolean
    LeadV1:
      type: object
      description: A canonical lead record — the pull counterpart to the `lead.*` event webhooks.
      properties:
        id:
          type: integer
          examples:
          - 12345
        team_id:
          type: integer
        created_at:
          type: string
          format: date-time
        received_at:
          type: string
          format: date-time
        status:
          type: string
          enum:
          - created
          - queued
          - processing
          - completed
          - failed
          - skipped
        source:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
              examples:
              - angi
            display_name:
              type: string
              examples:
              - Angi
            medium:
              type: string
              examples:
              - webhook
        external_id:
          type:
          - string
          - 'null'
          description: Third-party reference ID
        customer:
          type: object
          properties:
            name:
              type:
              - string
              - 'null'
            phone_number:
              type:
              - string
              - 'null'
            email:
              type:
              - string
              - 'null'
            address:
              type:
              - string
              - 'null'
            street:
              type:
              - string
              - 'null'
            city:
              type:
              - string
              - 'null'
            state:
              type:
              - string
              - 'null'
            zip:
              type:
              - string
              - 'null'
            country:
              type:
              - string
              - 'null'
            notes:
              type:
              - string
              - 'null'
        attribution:
          type: object
          properties:
            utm_source:
              type:
              - string
              - 'null'
            utm_medium:
              type:
              - string
              - 'null'
            utm_campaign:
              type:
              - string
              - 'null'
            utm_term:
              type:
              - string
              - 'null'
            utm_content:
              type:
              - string
              - 'null'
        contacted:
          type: boolean
          description: Whether any outreach touchpoint has occurred for this lead
        not_contacted_reason:
          type:
          - string
          - 'null'
          description: Why the lead has not been contacted, when `contacted` is false
        bookings:
          type: array
          description: Bookings attributed to this lead, deduped by CRM job ID and sorted earliest-first
          items:
            type: object
            properties:
              st_job_id:
                type:
                - string
                - 'null'
              booked_at:
                type:
                - string
                - 'null'
                format: date-time
              job_type:
                type:
                - string
                - 'null'
        booked_job_id:
          type:
          - string
          - 'null'
          description: CRM job ID of the first booking, when present
        completed_at:
          type:
          - string
          - 'null'
          format: date-time
        raw:
          type: object
          description: Original third-party payload (omit with `include_raw=false`)
    TeamMeta:
      type: object
      properties:
        team_id:
          type: integer
    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
    LeadV0:
      type: object
      properties:
        id:
          type: string
          format: uuid
        datetime:
          type: string
          format: date-time
        type:
          type: string
          enum:
          - call
          - scheduling_widget
          - web_chat
          - text
          - google_lsa
        customer_phone:
          type:
          - string
          - 'null'
        customer_email:
          type:
          - string
          - 'null'
        lead_content:
          type: object
          description: Channel-specific lead content
        agent:
          type:
          - string
          - 'null'
          description: Assistant ID that handled the touchpoint
        referrer_url:
          type:
          - string
          - 'null'
        attribution:
          type: object
          properties:
            utm_source:
              type:
              - string
              - 'null'
            gclid:
              type:
              - string
              - 'null'
  responses:
    Forbidden:
      description: API key lacks the required permission or team access
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key in the format `avoca_<64 hex characters>`