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

# List a segment's contacts

> Retrieve the segment's members as a paginated list of contacts, in the same shape as the
Contacts API, most recently created first.

Membership is computed periodically, so the list may be up to an hour old (see
`counts.refreshed_at` on the segment). If the segment's membership has **never** been computed,
this endpoint returns `202 Accepted`, starts the computation in the background, and you should
retry shortly.

Every member is returned whatever their consent state, so `pagination.total_count` is the
segment's total membership. It is neither the segment's `mailable_count` nor its
`textable_count` — those are consent-filtered counts taken at the last refresh.

**Required scope:** `segments_read`




## OpenAPI

````yaml openapi/privy-api.yaml GET /segments/{id}/contacts
openapi: 3.1.0
info:
  title: Privy API
  version: '1.0'
  description: >
    The Privy API lets you programmatically manage your contact list and read
    what you have set up in Privy.

    Create, update, unsubscribe, and remove contacts; report orders;

    and read your campaigns, flows, segments, orders, store products, coupon
    pools,

    performance reports, and account setup.
servers:
  - url: https://api.privy.com/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Account
    description: Retrieve information about the authenticated Privy account.
  - name: Contacts
    description: Manage your contact list.
  - name: Imports
    description: >-
      Read your contact import history — CSV uploads, connected-provider syncs,
      and SMS consent imports.
  - name: Campaigns
    description: >-
      Read your message campaigns — email and SMS newsletters, plus the messages
      your flows send.
  - name: Displays
    description: >-
      Read your on-site displays (popups, flyouts, banners, embedded forms,
      landing pages).
  - name: Coupons
    description: Read your coupon pools, their code inventory, and individual codes.
  - name: Reports
    description: >-
      Read performance reporting — signups, views, conversion rates, and
      attributed revenue — for your business, displays, and flows.
  - name: Flows
    description: Read your automation flows and their configuration.
  - name: Segments
    description: Read your customer segments and their membership.
  - name: Orders
    description: Report orders placed in your store and read your order history.
  - name: Products
    description: Read the product catalog and collections of your connected store.
  - name: Events
    description: Ingest custom events to trigger Flows and other automations.
paths:
  /segments/{id}/contacts:
    get:
      tags:
        - Segments
      summary: List a segment's contacts
      description: >
        Retrieve the segment's members as a paginated list of contacts, in the
        same shape as the

        Contacts API, most recently created first.


        Membership is computed periodically, so the list may be up to an hour
        old (see

        `counts.refreshed_at` on the segment). If the segment's membership has
        **never** been computed,

        this endpoint returns `202 Accepted`, starts the computation in the
        background, and you should

        retry shortly.


        Every member is returned whatever their consent state, so
        `pagination.total_count` is the

        segment's total membership. It is neither the segment's `mailable_count`
        nor its

        `textable_count` — those are consent-filtered counts taken at the last
        refresh.


        **Required scope:** `segments_read`
      operationId: listSegmentContacts
      parameters:
        - $ref: '#/components/parameters/AccountIdParam'
        - name: id
          in: path
          required: true
          description: >-
            The segment's unique identifier (returned as `id` in segment
            responses). Ids are opaque public strings — a numeric id from a
            Privy dashboard URL is not a valid API id and will 404; list
            segments and match by name instead.
          schema:
            type: string
          example: Rz5T2kW8pB
        - $ref: '#/components/parameters/PageParam'
        - $ref: '#/components/parameters/PerPageParam'
      responses:
        '200':
          description: A paginated list of the segment's member contacts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
                  pagination:
                    $ref: '#/components/schemas/PaginationEnvelope'
              example:
                data:
                  - id: cus_a1b2c3d4e5f6g7h8
                    first_name: Jane
                    last_name: Doe
                    email: jane@example.com
                    email_consent: subscribed
                    email_consent_at: '2025-03-20T14:22:00Z'
                    phone_number: '+15551234567'
                    sms_consent: subscribed
                    sms_consent_at: '2025-03-20T14:22:00Z'
                    source: csv
                    source_type: import
                    imported: true
                    import_ids:
                      - im_k2R5m8Q
                    tags:
                      - vip
                    created_at: '2025-01-15T10:30:00Z'
                    updated_at: '2025-03-20T14:22:00Z'
                pagination:
                  page: 1
                  per_page: 40
                  total_count: 1240
                  total_pages: 31
        '202':
          description: >
            The segment's membership has never been computed. Computation has
            been started — retry in a little while.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - processing
                    example: processing
                  message:
                    type: string
                    example: Segment membership is being computed. Check back shortly.
              example:
                status: processing
                message: Segment membership is being computed. Check back shortly.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/ContactsNotReady'
        '429':
          $ref: '#/components/responses/RateLimited'
      security:
        - bearerAuth: []
components:
  parameters:
    AccountIdParam:
      name: Privy-Account-Id
      in: header
      required: false
      description: >
        Target a subaccount instead of the main connected account.

        Pass a subaccount `id` from get_account's `subaccounts` list. Only
        direct subaccounts

        of the connected account are reachable — omit this for the main account
        itself.
      schema:
        type: string
      example: S1U2B3A4C5C6T7
    PageParam:
      name: page
      in: query
      description: Page number (starts at 1).
      schema:
        type: integer
        default: 1
        minimum: 1
      example: 1
    PerPageParam:
      name: per_page
      in: query
      description: >-
        Number of results per page. Values outside 10–100 are clamped to the
        nearest bound.
      schema:
        type: integer
        default: 40
        minimum: 10
        maximum: 100
      example: 40
  schemas:
    Contact:
      type: object
      description: >
        A contact in your Privy account: identity, marketing consent per
        channel, tags, and custom

        fields. Email and SMS consent are tracked independently — a contact who
        opts out of one

        keeps whatever consent they had for the other.
      properties:
        id:
          type: string
          description: >-
            Stable, unique identifier for the contact. Use this value in
            `/v1/contacts/{id}` endpoints.
          example: cus_a1b2c3d4e5f6g7h8
        first_name:
          type:
            - string
            - 'null'
          example: Jane
        last_name:
          type:
            - string
            - 'null'
          example: Doe
        email:
          type:
            - string
            - 'null'
          format: email
          example: jane@example.com
        email_consent:
          type: string
          enum:
            - subscribed
            - unsubscribed
            - never_subscribed
            - suppressed
            - compliance_suppressed
          description: >
            The contact's email marketing consent. `subscribed` is the only
            value that makes a

            contact mailable; Privy sends no marketing email to any of the other
            four.


            - `subscribed` — the contact has opted in. Covers both explicit
            consent (they ticked an
              email opt-in box, confirmed a double opt-in, or were subscribed through this API) and
              implicit consent (they gave you their address while buying, or arrived in an approved
              "subscribed" import). The two are not distinguished here.
            - `unsubscribed` — the contact opted out, typically through the
            preferences link in a
              Privy email. A later signup that provides consent resubscribes them.
            - `never_subscribed` — no opt-in and no opt-out on record; shown as
            "unset" in the Privy
              dashboard. This is the usual state for someone who bought without opting in, and for
              an imported contact whose import is still awaiting review.
            - `suppressed` — you suppressed the contact, from the dashboard or
            by writing
              `suppressed` to this field. Reversible: writing any other consent value unsuppresses
              the contact first, then applies the change you asked for.
            - `compliance_suppressed` — Privy suppressed the address to protect
            your sending
              reputation: a hard bounce, a spam complaint, a rejected delivery, an address that
              failed Privy's compliance check during an import, or a flow's Suppress Contact action.
              Read-only through this API — a write to this field returns `422`, and a later signup
              does not resubscribe them. Other fields on the contact remain editable.
          example: subscribed
        email_consent_at:
          type:
            - string
            - 'null'
          format: date-time
          description: |
            When `email_consent` last changed. Null when consent was never set.
          example: '2025-03-20T14:22:00Z'
        phone_number:
          type:
            - string
            - 'null'
          example: '+15551234567'
        sms_consent:
          type: string
          enum:
            - subscribed
            - unsubscribed
            - never_subscribed
            - single_opt_in
            - pending
          description: >
            The contact's SMS marketing consent. `subscribed` is the only value
            that makes a contact

            textable; Privy sends no marketing text to any of the other four.


            - `subscribed` — the contact's SMS opt-in is confirmed. Reached by
            replying `Y` to a
              double opt-in text, by signing up on a display set to Single Opt-In, by replying
              `START` or `UNSTOP`, by an opt-in recorded through this API, by a CSV import of
              SMS consent, or by a synced consent status from a connected store provider
              (e.g. Shopify). A confirmed opt-in does not record which method produced it:
              Single Opt-In and Double Opt-In displays both land on `subscribed`, so this field
              cannot tell you whether a contact double-opted in.
            - `unsubscribed` — the contact opted out, normally by replying
            `STOP`. Unlike email
              compliance suppression this is reversible: a new confirmed opt-in subscribes them again.
            - `never_subscribed` — no opt-in and no opt-out on record. Also the
            value after a
              reset: Privy clears SMS consent to this state when the phone number is removed from
              the contact, when a carrier reports the number as a landline, and when
              `never_subscribed` is written through this API. A contact who completed the SMS step
              of a multi-step display and has not yet replied `Y` also reads `never_subscribed` —
              that flow holds the opt-in off the contact record until it is confirmed — so do not
              read this value as "Privy never asked".
            - `single_opt_in` — a transitional pre-confirmation state inside the
            double opt-in
              flow, and the only pre-confirmation state a display signup can leave a contact in.
              The contact submitted a single-step display whose SMS opt-in method is Double Opt-In
              (Privy's default): the phone number is recorded, consent is not yet confirmed, and
              Privy is about to send the `Reply Y` confirmation text. In the healthy path the
              contact leaves this state within seconds — `pending` once the confirmation text is
              accepted by the carrier, then `subscribed` on the `Y` reply. A contact who stays
              here is one whose confirmation text was never sent (unsupported region, non-mobile
              number, SMS sending disabled on the account) or one written here directly through
              this API, which sends no confirmation text and so has no way forward. Not textable.
              Despite the name this is not the display's Single Opt-In setting — a display set to
              Single Opt-In confirms the contact outright, which reads as `subscribed`.
            - `pending` — Privy sent the double opt-in confirmation text and is
            waiting for the
              `Y` reply. Only reachable from `single_opt_in`, and only on the single-step display
              flow; the multi-step display flow tracks its awaiting-reply opt-ins outside this
              field. Not textable. Read-only.
          example: subscribed
        sms_consent_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When `sms_consent` last changed. Null when consent was never set.
          example: '2025-03-20T14:22:00Z'
        source:
          type:
            - string
            - 'null'
          description: >
            How the contact RECORD was created: an import mechanism (`csv`,
            `shopify`,

            `mailchimp`, …), a Privy display, or the API. Free-form vocabulary —
            new

            integrations add values. This is not signup attribution: a store
            webhook or

            sync can create the record before the visitor ever signs up on a
            display, and

            a later display signup does not rewrite it. For which display(s) a
            contact

            signed up on, read `signups` on `GET /v1/contacts/{id}`.
          example: csv
        source_type:
          type:
            - string
            - 'null'
          description: >
            The kind of origin behind `source`. Common values: `import` (arrived
            in a contact

            import or store sync), `web` (signed up on a display), `hook`
            (created by a store

            webhook — e.g. `source: shopify, source_type: hook` is a contact
            first seen through

            a Shopify order or customer webhook). Same caveat as `source`:
            describes record

            creation, not later display signups.
          example: import
        imported:
          type:
            - boolean
            - 'null'
          description: Whether the contact arrived in a contact import.
          example: true
        import_ids:
          type: array
          items:
            type: string
          description: >
            The email contact imports that touched this contact, oldest first.
            SMS consent

            imports are tracked separately and are not referenced here.
          example:
            - im_k2R5m8Q
        tags:
          type: array
          items:
            type: string
          description: >
            The contact's Privy tags — free-form labels you define, with no
            fixed vocabulary. Privy

            lower-cases each name, trims surrounding whitespace, and drops
            duplicates on save, so tags

            always read back normalized. A name Privy has not seen for the
            account before is

            registered automatically and becomes available for contact
            filtering, segment conditions,

            and tag-triggered flows.


            Tags reach a contact from a CSV import, the contact's profile, a
            bulk action on the

            Contacts page, a display's signup tagging, a flow's Tag Contact
            action, and this API.

            Tags synced from Shopify are stored separately and are not included
            here.
          example:
            - vip
            - repeat-buyer
        custom_fields:
          type: object
          description: >
            The contact's custom field values. Values are usually strings, but
            integration-written fields

            can carry other JSON scalars (e.g. numeric loyalty point balances).
          additionalProperties: true
          example:
            loyalty_tier: gold
            referral_code: JANE2024
        created_at:
          type: string
          format: date-time
          example: '2025-01-15T10:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2025-03-20T14:22:00Z'
    PaginationEnvelope:
      type: object
      properties:
        page:
          type: integer
          example: 1
        per_page:
          type: integer
          example: 25
        total_count:
          type: integer
          example: 142
        total_pages:
          type: integer
          example: 6
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - invalid_client
                - invalid_scope
                - unauthorized
                - insufficient_scope
                - paid_plan_required
                - api_access_required
                - not_found
                - no_connected_store
                - conflict
                - contacts_not_ready
                - validation_failed
                - rate_limited
                - store_unavailable
              example: validation_failed
            message:
              type: string
              example: One or more fields are invalid
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                    example: email
                  message:
                    type: string
                    example: is required
  responses:
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: unauthorized
              message: Bearer token is missing or invalid
    InsufficientScope:
      description: Token lacks the required scope for this endpoint.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: insufficient_scope
              message: Token does not have the required scope
    NotFound:
      description: >-
        The requested resource does not exist or does not belong to your
        account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: not_found
              message: Not found
    ContactsNotReady:
      description: >
        The account's contacts have not been assigned public API ids, so contact
        reads

        are unavailable. This happens when contacts were saved before the
        account had

        API access. Enable API access for the account, or have Privy staff run
        the

        public_id backfill task for it, then retry.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: contacts_not_ready
              message: >-
                This account's contacts have not been assigned public API ids,
                so contact reads are unavailable. Enable API access for the
                account, or have Privy staff run the public_id backfill task for
                it, then retry.
    RateLimited:
      description: Rate limit exceeded. Retry after the specified time.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
          example: 42
        X-RateLimit-Limit-Minute:
          description: Maximum requests allowed per minute.
          schema:
            type: integer
          example: 60
        X-RateLimit-Remaining-Minute:
          description: Requests remaining in the current minute window.
          schema:
            type: integer
          example: 0
        X-RateLimit-Reset-Minute:
          description: Unix timestamp when the minute window resets.
          schema:
            type: integer
          example: 1711929600
        X-RateLimit-Limit-Day:
          description: Maximum requests allowed per day.
          schema:
            type: integer
          example: 10000
        X-RateLimit-Remaining-Day:
          description: Requests remaining in the current day window.
          schema:
            type: integer
          example: 9500
        X-RateLimit-Reset-Day:
          description: Unix timestamp when the day window resets.
          schema:
            type: integer
          example: 1712016000
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API token or OAuth access token
      description: >
        Send either an API token or an OAuth access token as

        `Authorization: Bearer <token>`. See the Authentication page for
        details.

````