# List contacts

> List contacts with their channels. A repeated tag means all of them.

`GET https://api.zavu.dev/v2/contacts`

List contacts with their channels. A repeated `tag` means all of them.

## Parameters

- `search` (query, string)
- `bsuid` (query, string): Exact WhatsApp business-scoped user ID (e.g. `CO.13491208655302741918`). Returns the contact that holds it, or an empty list. Combines with `phoneNumber` and `tag` as a filter, and cannot be combined with `search` (400). A value that is not shaped like a BSUID returns 400.
- `tag` (query, string[])
- `limit` (query, integer)
- `cursor` (query, string): Opaque `nextCursor` from the previous page.

## Responses

### 200

Contacts.

- `items` (object[], required)
  - `id` (string, required)
  - `displayName` (string): Display name for the contact.
  - `phoneNumber` (string): DEPRECATED: Use primaryPhone instead. Primary phone number in E.164 format.
  - `primaryPhone` (string): Primary phone number in E.164 format.
  - `primaryEmail` (string<email>): Primary email address.
  - `countryCode` (string)
  - `profileName` (string, nullable): Contact's WhatsApp profile name. Only available for WhatsApp contacts.
  - `whatsapp` (object): WhatsApp identity. Present when Zavu has a business-scoped user ID (BSUID) for the contact, and absent otherwise. A contact with a username can be reached under its BSUID, its phone number, or both; they are the same contact. Look one up by BSUID with the `bsuid` query parameter of the list endpoint.
    - `bsuid` (string, required): Business-scoped user ID. Can be used as `to` when sending.
    - `username` (string): The WhatsApp username, when Meta reported one.
  - `availableChannels` (string[], required): List of available messaging channels for this contact.
  - `defaultChannel` (string): Preferred channel for this contact. One of: `sms`, `whatsapp`, `telegram`, `email`, `instagram`, `messenger`, `voice`.
  - `verified` (boolean, required): Whether this contact has been verified.
  - `channels` (object[]): All communication channels for this contact.
    - `id` (string, required)
    - `channel` (string, required): Channel type. One of: `sms`, `whatsapp`, `email`, `telegram`, `instagram`, `messenger`, `voice`.
    - `identifier` (string, required): Channel identifier (phone number or email address).
    - `countryCode` (string): ISO country code for phone numbers.
    - `label` (string): Optional label for the channel.
    - `isPrimary` (boolean, required): Whether this is the primary channel for its type.
    - `verified` (boolean, required): Whether this channel has been verified.
    - `metrics` (object): Delivery metrics for this channel.
      - `successCount` (integer)
      - `failureCount` (integer)
      - `totalAttempts` (integer)
      - `avgDeliveryTimeMs` (number)
      - `lastSuccessAt` (string<date-time>)
    - `lastInboundAt` (string<date-time>): Last time a message was received on this channel.
    - `metadata` (object)
      - `{key}` (string)
    - `createdAt` (string<date-time>, required)
    - `updatedAt` (string<date-time>)
  - `metadata` (object, required)
    - `{key}` (string)
  - `createdAt` (string<date-time>, required)
  - `updatedAt` (string<date-time>)
- `nextCursor` (string, nullable)

### 400

Unknown tag.

- `code` (string, required)
- `message` (string, required)
- `details` (object): Machine-readable context. Keys that mean the same thing everywhere: - `errors`: present on every `400 invalid_request` for an invalid body or query parameter, `[{path, message, ...}]`, `path` naming the field (`["to"]`, `["contacts", 2, "recipient"]`, `["limit"]`). - `recommendation`: one sentence saying what to do next. - `dashboardUrl`: the dashboard screen that fixes it. - `connect`: on `409 no_channel`, the channels this project can connect to reach the recipient, each `{type, request, note, available, dashboardUrl?}`; `request` is the exact call (`POST /v2/channels` with its body, or `POST /v2/numbers`), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger). `available: false` says why in `note` (one-way SMS closed until business verification is approved). - `address` / `from`: the address the error is about, under the name the request used for it.
  - `errors` (object[])
    - `path` (object[], required)
    - `message` (string, required)
    - `code` (string)

### 401

Unauthorized.

- `code` (string, required)
- `message` (string, required)
- `details` (object): Machine-readable context. Keys that mean the same thing everywhere: - `errors`: present on every `400 invalid_request` for an invalid body or query parameter, `[{path, message, ...}]`, `path` naming the field (`["to"]`, `["contacts", 2, "recipient"]`, `["limit"]`). - `recommendation`: one sentence saying what to do next. - `dashboardUrl`: the dashboard screen that fixes it. - `connect`: on `409 no_channel`, the channels this project can connect to reach the recipient, each `{type, request, note, available, dashboardUrl?}`; `request` is the exact call (`POST /v2/channels` with its body, or `POST /v2/numbers`), or null for a channel connected from the dashboard (WhatsApp, Instagram, Messenger). `available: false` says why in `note` (one-way SMS closed until business verification is approved). - `address` / `from`: the address the error is about, under the name the request used for it.
  - `errors` (object[])
    - `path` (object[], required)
    - `message` (string, required)
    - `code` (string)

## Example

```bash
curl -X GET "https://api.zavu.dev/v2/contacts?bsuid=CO.13491208655302741918" \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY"
```

```typescript
import Zavudev from "@zavudev/sdk";

const zavu = new Zavudev({ apiKey: process.env.ZAVUDEV_API_KEY });

const result = await zavu.v2.contacts.list({
  bsuid: "CO.13491208655302741918",
});

console.log(result);
```
