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

# List a campaign's conversion records

> One row per call that post-call analysis scored as an outcome — never-dialed, unanswered, and ungraded contacts are absent. Newest first. This route returns the stored record as-is; [`/campaigns/{campaignId}/results`](/api-reference/campaign-outcomes/list-a-campaigns-outcomes) serves the same rows joined to each contact's name and phone and labelled with the campaign's goal vocabulary, which is the easier one to render.

**Note:** Scores, conversions, and sentiment are computed by LLMs — best effort, with room to be wrong. We are continuously closing the tracking gaps, but for sensitive workloads we recommend running your own analysis on the transcripts delivered over [webhooks](/voice-agents/webhooks/overview).



## OpenAPI

````yaml /voice-agents/api-reference/openapi.yaml get /campaigns/{campaignId}/conversions
openapi: 3.1.0
info:
  title: UpliftAI Voice Agents API
  version: '1.0'
  description: >-
    Build voice assistants, start conversations on the web or the phone, run
    calling campaigns, and receive outcomes by webhook. All endpoints take a
    bearer API key unless noted otherwise.
servers:
  - url: https://api.upliftai.org/v1
security:
  - apiKey: []
tags:
  - name: Assistants
  - name: Authoring an assistant
  - name: Starting a conversation
  - name: Sessions & call records
  - name: Campaigns
  - name: Campaign outcomes
  - name: Contacts
  - name: Google Sheet sources
  - name: Integrations & delivery health
paths:
  /campaigns/{campaignId}/conversions:
    get:
      tags:
        - Campaign outcomes
      summary: List a campaign's conversion records
      description: >-
        One row per call that post-call analysis scored as an outcome —
        never-dialed, unanswered, and ungraded contacts are absent. Newest
        first. This route returns the stored record as-is;
        [`/campaigns/{campaignId}/results`](/api-reference/campaign-outcomes/list-a-campaigns-outcomes)
        serves the same rows joined to each contact's name and phone and
        labelled with the campaign's goal vocabulary, which is the easier one to
        render.


        **Note:** Scores, conversions, and sentiment are computed by LLMs — best
        effort, with room to be wrong. We are continuously closing the tracking
        gaps, but for sensitive workloads we recommend running your own analysis
        on the transcripts delivered over
        [webhooks](/voice-agents/webhooks/overview).
      operationId: listCampaignConversions
      parameters:
        - name: campaignId
          in: path
          required: true
          schema:
            type: string
            format: uuid
          example: a5be4d9e-xxxx-xxxx-xxxx-xxxxxxxxxxxx
        - name: limit
          in: query
          required: false
          description: Rows per page. Values above 100 are capped to 100.
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          required: false
          description: The `nextCursor` from the previous page.
          schema:
            type: string
      responses:
        '200':
          description: One page of conversion records.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListConversionsResponse'
              examples:
                records:
                  summary: A lead campaign's first page
                  value:
                    conversions:
                      - sessionId: a5be4d9e-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923001234567#a1
                        organizationId: a12b7e74-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        projectId: c782a4ec-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        assistantId: 0f4a91d3-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        campaignId: a5be4d9e-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        goalKind: lead
                        payload:
                          kind: lead
                          status: qualified
                          interest: سائبر سیکیورٹی ڈپلومہ، شام والی کلاس
                          nextStep: جمعرات شام 6 بجے ڈیمو سیشن
                          notes: فیس کی قسطوں کے بارے میں پوچھا
                          summary: >-
                            عائشہ صدیقی کورس میں دلچسپی رکھتی ہیں اور ڈیمو کے
                            لیے تیار ہیں۔
                        date: '2026-08-18'
                        createdAt: '2026-08-18T09:12:44.831Z'
                      - sessionId: a5be4d9e-xxxx-xxxx-xxxx-xxxxxxxxxxxx#+923214455661#a2
                        organizationId: a12b7e74-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        projectId: c782a4ec-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        assistantId: 0f4a91d3-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        campaignId: a5be4d9e-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                        goalKind: lead
                        payload:
                          kind: lead
                          status: callback
                          interest: بی ایس سی کے بعد کے آپشنز
                          nextStep: کل دوپہر دوبارہ کال کریں
                          summary: بلال احمد ابھی مصروف تھے، کل بات کرنے کو کہا۔
                        date: '2026-08-18'
                        createdAt: '2026-08-18T08:47:02.118Z'
                    nextCursor: >-
                      eyJwayI6ICJhMTJiN2U3NC14eHh4LXh4eHgteHh4eC14eHh4eHh4eHh4eHgjYzc4MmE0ZWMteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwgInNrIjogImE1YmU0ZDllLXh4eHgteHh4eC14eHh4LXh4eHh4eHh4eHh4eCMrOTIzMjE0NDU1NjYxI2EyIiwgImNhbXBhaWduSWQiOiAiYTViZTRkOWUteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwgInNsb3RPckNyZWF0ZWQiOiAiMjAyNi0wOC0xOFQwODo0NzowMi4xMThaIn0
                empty:
                  summary: Nothing graded yet
                  value:
                    conversions: []
        '400':
          description: The `cursor` could not be decoded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: Invalid pagination cursor
                error: Bad Request
                statusCode: 400
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: No campaign under that id in the API key's project.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: 'Campaign not found: 00000000-0000-4000-8000-000000000000'
                error: Not Found
                statusCode: 404
components:
  schemas:
    ListConversionsResponse:
      type: object
      properties:
        conversions:
          type: array
          items:
            $ref: '#/components/schemas/ConversionRecord'
        nextCursor:
          type: string
          description: Absent on the last page.
    Error:
      type: object
      properties:
        message:
          description: >-
            One message per failed field for validation errors, a single string
            otherwise.
          oneOf:
            - type: string
            - type: array
              items:
                type: string
        error:
          type: string
        statusCode:
          type: integer
    ConversionRecord:
      type: object
      description: The outcome one graded call produced.
      properties:
        sessionId:
          type: string
          description: >-
            The call this outcome came from, built as
            `{campaignId}#{contactId}#a{attempt}`. `contactId` is the phone
            number as you supplied it, or `evt#{externalRef}` for appended
            contacts. Treat the id as opaque — those refs contain `#`
            themselves.
        organizationId:
          type: string
          format: uuid
        projectId:
          type: string
          format: uuid
        assistantId:
          type: string
          format: uuid
        campaignId:
          type: string
          format: uuid
        ref:
          type: string
          description: Currently always equal to `sessionId`.
        goalKind:
          type: string
          description: The campaign's goal, copied onto every row.
          enum:
            - appointment
            - event
            - lead
            - order_confirmation
            - payment_reminder
            - outreach
            - reservation_confirmation
        payload:
          $ref: '#/components/schemas/ConversionPayload'
        slotIso:
          type: string
          format: date-time
          description: >-
            The agreed appointment or event time, on goals that have one. Rows
            are ordered newest-first by this field, or by `createdAt` where it's
            absent.
        date:
          type: string
          format: date
          description: >-
            Day bucket for this outcome, in the campaign's calling-window
            timezone rather than UTC.
        createdAt:
          type: string
          format: date-time
          description: When post-call analysis graded the call, not when it was placed.
    ConversionPayload:
      description: >-
        What the agent got out of the call. `kind` tracks the campaign's
        `goalKind`, except that an `event` campaign records `rsvp` payloads.
        Every field but `kind` is best-effort — the agent omits whatever the
        caller never said.
      oneOf:
        - title: Appointment
          type: object
          properties:
            kind:
              type: string
              const: appointment
            outcome:
              type: string
            summary:
              type: string
        - title: RSVP
          type: object
          properties:
            kind:
              type: string
              const: rsvp
            outcome:
              type: string
              enum:
                - confirmed
                - maybe
            party:
              type: integer
              minimum: 1
              description: Headcount the caller is bringing, including themselves.
            summary:
              type: string
        - title: Lead
          type: object
          properties:
            kind:
              type: string
              const: lead
            outcome:
              type: string
            status:
              type: string
              enum:
                - qualified
                - callback
                - not_interested
                - wrong_person
                - needs_human
            interest:
              type: string
            nextStep:
              type: string
            notes:
              type: string
            summary:
              type: string
        - title: Order confirmation
          type: object
          properties:
            kind:
              type: string
              const: order_confirmation
            status:
              type: string
              enum:
                - confirmed
                - cancelled
                - amended
                - address_incomplete
                - wrong_person
                - callback
            address:
              type: string
              description: Delivery address as the caller gave or corrected it.
            orderId:
              type: string
            orderValue:
              type: object
              properties:
                amount:
                  type: number
                currency:
                  type: string
            summary:
              type: string
        - title: Payment reminder
          type: object
          properties:
            kind:
              type: string
              const: payment_reminder
            status:
              type: string
              enum:
                - will_pay
                - already_paid
                - dispute
                - callback
                - wrong_person
            promiseDate:
              type: string
              description: The date the caller committed to pay by.
            summary:
              type: string
        - title: Outreach
          type: object
          properties:
            kind:
              type: string
              const: outreach
            status:
              type: string
              enum:
                - interested
                - callback
                - not_interested
                - wrong_person
            summary:
              type: string
        - title: Reservation confirmation
          type: object
          properties:
            kind:
              type: string
              const: reservation_confirmation
            status:
              type: string
              enum:
                - confirmed
                - cancelled
                - rescheduled
                - wrong_person
                - callback
            party:
              type: integer
              minimum: 1
            reservationTime:
              type: string
            summary:
              type: string
  responses:
    Unauthorized:
      description: A bearer key was sent but is not recognized.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: invalid authorization
            error: Unauthorized
            statusCode: 401
    Forbidden:
      description: No API key sent, or the key lacks permission for this resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            message: Forbidden resource
            error: Forbidden
            statusCode: 403
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: Project API key (`sk_api_…`).

````