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

# Contacts

> Look up contacts, verify phone numbers, and retrieve profile pictures before sending messages.

# Contacts

The Contacts API lets you verify phone numbers on WhatsApp, retrieve contact information, and fetch profile pictures. This is especially useful for validating numbers before sending messages and enriching your contact data.

All contact endpoints are scoped to a specific instance:

```
/api/instances/{instanceId}/contacts/...
```

***

## Check if a Number Exists

Verify whether a phone number is registered on WhatsApp before sending a message. This prevents failed deliveries and wasted API calls.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.wappfy.io/api/instances/inst_abc123/contacts/check?phone=5511999998888" \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.wappfy.io/api/instances/inst_abc123/contacts/check?phone=5511999998888",
    {
      headers: { "X-Api-Key": "YOUR_API_KEY" },
    }
  );

  const { data } = await response.json();
  if (data.exists) {
    console.log(`Number exists on WhatsApp: ${data.chat_id}`);
  } else {
    console.log("Number is not on WhatsApp");
  }
  ```
</CodeGroup>

**Response (number exists):**

```json theme={null}
{
  "data": {
    "exists": true,
    "phone": "5511999998888",
    "chat_id": "5511999998888@s.whatsapp.net"
  }
}
```

**Response (number does not exist):**

```json theme={null}
{
  "data": {
    "exists": false,
    "phone": "5511999998888",
    "chat_id": null
  }
}
```

<Tip>
  Use this endpoint to validate numbers before sending messages. It saves on message quota and prevents `message.failed` webhook events.
</Tip>

***

## Get All Contacts

Retrieve the full contact list for the connected WhatsApp account.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.wappfy.io/api/instances/inst_abc123/contacts \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.wappfy.io/api/instances/inst_abc123/contacts",
    {
      headers: { "X-Api-Key": "YOUR_API_KEY" },
    }
  );

  const { data } = await response.json();
  console.log(`Total contacts: ${data.length}`);
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "data": [
    {
      "id": "5511999998888@s.whatsapp.net",
      "name": "Maria Silva",
      "short_name": "Maria",
      "push_name": "Mari",
      "is_business": false
    },
    {
      "id": "5511888887777@s.whatsapp.net",
      "name": "Carlos Oliveira",
      "short_name": "Carlos",
      "push_name": "Carlos",
      "is_business": true
    }
  ]
}
```

### Contact Fields

| Field         | Description                                                                    |
| ------------- | ------------------------------------------------------------------------------ |
| `id`          | The contact's WhatsApp ID (phone number + `@s.whatsapp.net`).                  |
| `name`        | Contact name as saved in the phone's address book. May be `null` if not saved. |
| `short_name`  | Short name from the address book.                                              |
| `push_name`   | The name the contact has set for themselves on WhatsApp.                       |
| `is_business` | Whether this is a WhatsApp Business account.                                   |

<Note>
  The `name` field comes from your phone's address book. If the contact is not saved, only `push_name` (set by the contact themselves) will be available.
</Note>

***

## Get Contact Info

Retrieve detailed information about a specific contact.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.wappfy.io/api/instances/inst_abc123/contacts/5511999998888@s.whatsapp.net" \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.wappfy.io/api/instances/inst_abc123/contacts/5511999998888@s.whatsapp.net",
    {
      headers: { "X-Api-Key": "YOUR_API_KEY" },
    }
  );

  const { data } = await response.json();
  console.log(`Contact: ${data.push_name || data.name}`);
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "data": {
    "id": "5511999998888@s.whatsapp.net",
    "name": "Maria Silva",
    "short_name": "Maria",
    "push_name": "Mari",
    "is_business": false
  }
}
```

***

## Get Profile Picture

Retrieve a contact's WhatsApp profile picture URL.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.wappfy.io/api/instances/inst_abc123/contacts/5511999998888@s.whatsapp.net/profile-picture" \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    "https://api.wappfy.io/api/instances/inst_abc123/contacts/5511999998888@s.whatsapp.net/profile-picture",
    {
      headers: { "X-Api-Key": "YOUR_API_KEY" },
    }
  );

  const { data } = await response.json();
  if (data.profile_picture_url) {
    console.log(`Profile picture: ${data.profile_picture_url}`);
  } else {
    console.log("No profile picture set");
  }
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "data": {
    "profile_picture_url": "https://pps.whatsapp.net/v/t61.24694-24/..."
  }
}
```

<Note>
  Profile picture URLs are temporary and expire after some time. Do not store them permanently -- fetch a fresh URL when needed.
</Note>

If the contact has no profile picture or has restricted visibility in their privacy settings, the `profile_picture_url` will be `null`:

```json theme={null}
{
  "data": {
    "profile_picture_url": null
  }
}
```

***

## Common Patterns

### Validate Before Sending

Always check if a number exists on WhatsApp before sending a message to avoid unnecessary failures:

```javascript theme={null}
async function sendMessageSafely(instanceId, phone, text) {
  // Step 1: Check if the number is on WhatsApp
  const checkResponse = await fetch(
    `https://api.wappfy.io/api/instances/${instanceId}/contacts/check?phone=${phone}`,
    { headers: { "X-Api-Key": "YOUR_API_KEY" } }
  );
  const { data: checkResult } = await checkResponse.json();

  if (!checkResult.exists) {
    console.log(`${phone} is not on WhatsApp, skipping`);
    return null;
  }

  // Step 2: Send the message using the confirmed chat_id
  const sendResponse = await fetch(
    `https://api.wappfy.io/api/instances/${instanceId}/messages/send`,
    {
      method: "POST",
      headers: {
        "X-Api-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        chat_id: checkResult.chat_id,
        type: "text",
        text,
      }),
    }
  );

  return sendResponse.json();
}
```

### Build a Contact Directory

Fetch all contacts and enrich them with profile pictures:

```javascript theme={null}
async function buildContactDirectory(instanceId) {
  // Get all contacts
  const contactsRes = await fetch(
    `https://api.wappfy.io/api/instances/${instanceId}/contacts`,
    { headers: { "X-Api-Key": "YOUR_API_KEY" } }
  );
  const { data: contacts } = await contactsRes.json();

  // Enrich with profile pictures (batch with delay to avoid rate limits)
  const enriched = [];
  for (const contact of contacts) {
    const picRes = await fetch(
      `https://api.wappfy.io/api/instances/${instanceId}/contacts/${contact.id}/profile-picture`,
      { headers: { "X-Api-Key": "YOUR_API_KEY" } }
    );
    const { data: pic } = await picRes.json();

    enriched.push({
      ...contact,
      profile_picture_url: pic.profile_picture_url,
    });

    // Small delay to respect rate limits
    await new Promise((r) => setTimeout(r, 200));
  }

  return enriched;
}
```

<Warning>
  When fetching profile pictures for many contacts, add a delay between requests to stay within [rate limits](/rate-limits). The example above uses a 200ms delay.
</Warning>

***

## Endpoint Reference

| Method | Endpoint                                                   | Description                          |
| ------ | ---------------------------------------------------------- | ------------------------------------ |
| `GET`  | `/api/instances/{id}/contacts`                             | List all contacts                    |
| `GET`  | `/api/instances/{id}/contacts/check?phone={phone}`         | Check if a number exists on WhatsApp |
| `GET`  | `/api/instances/{id}/contacts/{contactId}`                 | Get contact info                     |
| `GET`  | `/api/instances/{id}/contacts/{contactId}/profile-picture` | Get profile picture                  |

***

## Error Handling

| Status Code | Description                                                                              |
| ----------- | ---------------------------------------------------------------------------------------- |
| `400`       | Invalid phone number format. Use digits only, with country code (e.g., `5511999998888`). |
| `404`       | Instance not found or contact not found.                                                 |
| `429`       | Rate limit exceeded. See [Rate Limits](/rate-limits).                                    |
