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

# List contacts

> Returns a list of contacts in your org.

**Pagination is driven by `limit`, not `page`.** The maximum page size is **50**:

- `limit` omitted, or `limit` ≥ 50 → paginated. `data` contains `page`, `pages`, `count` and `results`, and `message` is `"N contacts found"`.
- `limit` below 50 → **not** paginated. `data` contains only `results`, and `message` is `"success"`.

Contacts are always in `data.results` — never a flat array. Each result carries both `id` and `con_id` (the same value) alongside the contact's field keys.

Requires the **`contacts`** permission on the service account that owns your API key. A key whose service account lacks it fails with `"Lacking necessary permission contacts"`.

**Permission:** requires `contacts`.

**Custom fields appear flat, keyed by machine name.** In the example below `shirt_size`, `crew_role`, `hire_date`, `certification_expires` and `tags` are all org-defined — your org will have a different set. Two things to note about their values: date fields whose suffix is `First` or `Last` (and any relative-time field) come back as a **Unix timestamp** like `hire_date`, while other date fields are ISO-formatted like `certification_expires`; and every related-contact field also yields a `<field>_child_cnt` integer, such as `supervisor_child_cnt`. Use the `fields` parameter to project just the ones you need.



## OpenAPI

````yaml /api-reference/specs/contacts.json get /api/contacts
openapi: 3.1.0
info:
  title: ConveYour API — Contacts
  description: >-
    Contacts are the core data object in ConveYour. Every person in your system
    — a learner, rep, or prospect — is a contact.
  version: 1.0.0
servers:
  - url: https://{subdomain}.conveyour.com
    description: Your organization's ConveYour instance
    variables:
      subdomain:
        default: acme
        description: >-
          Your organization's slug — the subdomain you sign in on. Replace
          `acme` with yours: if you sign in at `bigco.conveyour.com`, enter
          `bigco`.
security:
  - conveyourToken: []
tags:
  - name: Contacts
    description: >-
      Contacts are the core data object in ConveYour. Every person in your
      system — a learner, rep, or prospect — is a contact.
paths:
  /api/contacts:
    get:
      tags:
        - Contacts
      summary: List contacts
      description: >-
        Returns a list of contacts in your org.


        **Pagination is driven by `limit`, not `page`.** The maximum page size
        is **50**:


        - `limit` omitted, or `limit` ≥ 50 → paginated. `data` contains `page`,
        `pages`, `count` and `results`, and `message` is `"N contacts found"`.

        - `limit` below 50 → **not** paginated. `data` contains only `results`,
        and `message` is `"success"`.


        Contacts are always in `data.results` — never a flat array. Each result
        carries both `id` and `con_id` (the same value) alongside the contact's
        field keys.


        Requires the **`contacts`** permission on the service account that owns
        your API key. A key whose service account lacks it fails with `"Lacking
        necessary permission contacts"`.


        **Permission:** requires `contacts`.


        **Custom fields appear flat, keyed by machine name.** In the example
        below `shirt_size`, `crew_role`, `hire_date`, `certification_expires`
        and `tags` are all org-defined — your org will have a different set. Two
        things to note about their values: date fields whose suffix is `First`
        or `Last` (and any relative-time field) come back as a **Unix
        timestamp** like `hire_date`, while other date fields are ISO-formatted
        like `certification_expires`; and every related-contact field also
        yields a `<field>_child_cnt` integer, such as `supervisor_child_cnt`.
        Use the `fields` parameter to project just the ones you need.
      operationId: listContacts
      parameters:
        - name: format
          in: query
          description: >-
            Use `v2` for the current response shape. Recommended for all new
            integrations.
          schema:
            type: string
            enum:
              - v2
        - name: archived
          in: query
          description: >-
            Filter by archive state. Omit for active only (default), `just` for
            archived only, `with` for all.
          schema:
            type: string
            enum:
              - just
              - with
        - name: search
          in: query
          description: Search contacts by name, email, or phone number.
          schema:
            type: string
        - name: filters
          in: query
          description: >-
            Filter contacts by field value. Use **Add property**: the property
            name is the contact field key, the value is what to match.
            Serialized as `filters[field_name]=value` — e.g.
            `filters[email]=jane@example.com`. Any contact field key works,
            including org-defined custom fields.
          style: deepObject
          explode: true
          schema:
            type: object
            additionalProperties:
              type: string
          example:
            email: jane@example.com
        - name: sort
          in: query
          description: >-
            Sort by field. Use **Add property**: the property name is the field
            key, the value is `1` (ascending) or `-1` (descending). Serialized
            as `sort[field_name]=1` — e.g. `sort[created_at]=-1`.
          style: deepObject
          explode: true
          schema:
            type: object
            additionalProperties:
              type: integer
              enum:
                - 1
                - -1
          example:
            created_at: -1
        - name: count
          in: query
          description: >-
            Pass `count=1` to return only a contact count instead of records.
            Response: `{ "message": "contacts count", "data": { "count": 142 }
            }`.
          schema:
            type: integer
            enum:
              - 1
        - name: page
          in: query
          description: >-
            Page number (1-based). Only has an effect when the response is
            paginated — i.e. when `limit` is omitted or is 50.
          schema:
            type: integer
            minimum: 1
        - name: limit
          in: query
          description: >-
            Maximum contacts per page. Capped at **50**, which is also the
            default. Passing a value below 50 turns pagination off — `data` then
            contains only `results`.
          schema:
            type: integer
            maximum: 50
            default: 50
        - name: fields
          in: query
          description: >-
            Comma-separated list of field keys to include in each contact
            (projection). Omit for all fields. `id`, `con_id` and `photo` are
            always returned.
          schema:
            type: string
          example: first_name,last_name,email
        - $ref: '#/components/parameters/teams'
        - name: expected_value
          in: query
          required: false
          description: >-
            CSV export only. What the encrypted column should contain. Defaults
            to `encrypted`.
          schema:
            type: string
        - name: public_key
          in: query
          required: false
          description: >-
            CSV export only. RSA public key used to encrypt sensitive columns.
            Required when the org enables `require_public_encryption_key`.
          schema:
            type: string
      responses:
        '200':
          description: A list of contacts. Shape depends on `limit` — see the description.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Envelope'
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          results:
                            type: array
                            items:
                              $ref: '#/components/schemas/Contact'
                          page:
                            type: integer
                            description: >-
                              Current page number. Present only when the request
                              paginates (limit >= limits.contacts).
                          pages:
                            type: integer
                            description: >-
                              Total number of pages. Present only when the
                              request paginates (limit >= limits.contacts).
                          count:
                            type: integer
                            description: >-
                              Total matching records across all pages. Present
                              only when the request paginates (limit >=
                              limits.contacts).
                        description: >-
                          Contacts plus pagination. page, pages and count are
                          present ONLY when the request paginates —
                          getPaginated() disables pagination whenever limit is
                          below limits.contacts, and then returns results alone.
                          Passing count=true instead returns just {count}.
              examples:
                paginated:
                  summary: Paginated (default)
                  description: >-
                    Returned when `limit` is at or above `limits.contacts`.
                    `page`, `pages` and `count` are present.
                  value:
                    status: ok
                    message: 38 contacts found
                    data:
                      page: 1
                      pages: 1
                      count: 38
                      results:
                        - id: 6a1445f03af9bb089d10e1ad
                          con_id: 6a1445f03af9bb089d10e1ad
                          first_name: Jane
                          last_name: Doe
                          email: jane@example.com
                          mobile: '+15555550100'
                          tags:
                            - onboarding
                            - southwest
                          shirt_size: L
                          crew_role: Installer
                          hire_date: 1718438400
                          certification_expires: '2027-03-14T00:00:00+00:00'
                          supervisor_child_cnt: 3
                flat:
                  summary: Small limit — no pagination keys
                  description: >-
                    `getPaginated()` turns pagination OFF when `limit` is below
                    `limits.contacts`. You get `results` alone — no `page`,
                    `pages` or `count`.
                  value:
                    status: ok
                    message: success
                    data:
                      results:
                        - id: 6a1445f03af9bb089d10e1ad
                          con_id: 6a1445f03af9bb089d10e1ad
                          first_name: Jane
                          last_name: Doe
                          email: jane@example.com
                          mobile: '+15555550100'
                          tags:
                            - onboarding
                            - southwest
                          shirt_size: L
                          crew_role: Installer
                          hire_date: 1718438400
                          certification_expires: '2027-03-14T00:00:00+00:00'
                          supervisor_child_cnt: 3
                count_only:
                  summary: count=true
                  description: >-
                    Passing `count=true` returns the match count and nothing
                    else — no records.
                  value:
                    status: ok
                    message: contacts count
                    data:
                      count: 38
        '403':
          description: The token lacks the `contacts` permission.
          content:
            application/json:
              example:
                status: failed
                message: Lacking necessary permission contacts
                data:
                  permission: contacts
components:
  parameters:
    teams:
      name: teams[]
      in: query
      description: >-
        Team scope for the request, as one or more team ObjectIds. The brackets
        are required: PHP keeps only the last value for a repeated plain key, so
        `teams=A&teams=B` silently resolves to B alone. On requests with a JSON
        body you may send `teams` (no brackets) in the body instead.


        **Values that are not valid ObjectIds are silently ignored** — a
        mistyped team ID behaves as if no team was sent. See the [teams section
        of the API conventions guide](/guides/api-conventions#team-scoping).
      style: form
      explode: true
      schema:
        type: array
        items:
          type: string
      example:
        - 64a1b2c3d4e5f6a7b8c9d0ff
  schemas:
    Envelope:
      type: object
      description: The common response envelope shared by all ConveYour endpoints.
      properties:
        status:
          type: string
          enum:
            - ok
            - failed
          description: '`ok` on success, `failed` on error.'
        message:
          type: string
          description: Human-readable description of the result.
        data:
          description: >-
            The response payload — an object or an array depending on the
            endpoint.
    Contact:
      type: object
      description: >-
        A contact as returned by the LIST endpoint. Custom fields appear FLAT at
        the top level keyed by their machine name (not their label), and no
        display name is synthesised. Use the fields query parameter to project a
        subset.
      properties:
        con_id:
          type: string
          description: Contact ID. Always present — Sets it explicitly.
        con_pid:
          type: string
          description: >-
            Public ID. Present ONLY when `con_pid` is included in the `fields`
            query parameter.
        id:
          type: string
          description: Record ID from the underlying attributes.
        email:
          type: string
          description: Present when the org defines an email field.
        first_name:
          type: string
          description: Present when the org defines a first_name field.
        last_name:
          type: string
          description: Present when the org defines a last_name field.
        mobile:
          type: string
          description: Present when the org defines a mobile field.
      additionalProperties:
        description: >-
          Any org-defined contact field, keyed by machine name. Fields whose
          suffix is First or Last, and any relative-time field, are returned as
          a Unix timestamp; other date fields are ISO formatted. Related-contact
          fields also produce a <field>_child_cnt integer.
  securitySchemes:
    conveyourToken:
      type: apiKey
      in: header
      name: x-conveyour-token
      description: >-
        Your API key token. Contacts endpoints require a **Server-only — Full
        API** key — see [Authentication](/quickstart).

````

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