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

# Get contacts by status

> Returns contacts filtered by status and calculates how long they have been waiting (from last_inbound_message.created_at until now). Adds a "waiting_time" field that represents (in seconds) how long that contact has been waiting. Sorted by waiting_time descending (longest wait first).

## Overview

Get contacts filtered by their conversation status (unattended, attended, ai-attended, ai-away) with calculated waiting times. This endpoint helps you identify contacts that need attention and prioritize responses based on how long they've been waiting.

Perfect for building priority queues, monitoring SLAs, and ensuring no customer is left waiting too long.

## Use Cases

* **Priority Queue**: Display contacts sorted by waiting time
* **SLA Monitoring**: Track contacts approaching SLA thresholds
* **Workload Distribution**: Identify unattended conversations for assignment
* **Response Urgency**: Find contacts waiting longest for response
* **Status Dashboard**: Monitor conversations by status
* **Customer Service Quality**: Ensure timely responses to all customers

## Authentication

This endpoint requires authentication using an API key. Include your API key in the request header:

```
x-api-key: your_api_key_here
```

## Query Parameters

| Parameter    | Type   | Required | Description                      |
| ------------ | ------ | -------- | -------------------------------- |
| `page`       | number | Yes      | Page number (starts at 1)        |
| `status`     | string | Yes      | Contact status to filter by      |
| `pipelineId` | string | No       | Filter by specific pipeline UUID |

### Status Values

| Status        | Description                                           |
| ------------- | ----------------------------------------------------- |
| `unattended`  | New messages not yet attended by team member          |
| `attended`    | Currently being handled by human team member          |
| `ai-attended` | Being handled by AI assistant                         |
| `ai-away`     | AI temporarily unavailable, waiting for human handoff |

## Response Structure

| Field   | Type   | Description                                 |
| ------- | ------ | ------------------------------------------- |
| `data`  | array  | Array of contact objects with waiting times |
| `total` | number | Total number of contacts matching criteria  |

### Contact Object

| Field              | Type           | Description                            |
| ------------------ | -------------- | -------------------------------------- |
| `id`               | string (UUID)  | Contact's unique identifier            |
| `name`             | string         | Contact's name                         |
| `created_at`       | string (ISO)   | Contact creation timestamp             |
| `platform`         | string         | Communication channel                  |
| `chat_status`      | string         | Current chat status                    |
| `waiting_time`     | number         | Time waiting for response (in seconds) |
| `active_ticket_v2` | object \| null | Active ticket information              |
| `assigned_agents`  | array          | List of assigned team members          |

## Example Requests

### Get Unattended Contacts

```bash theme={null}
curl --request GET \
  'https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=unattended' \
  --header 'x-api-key: your_api_key_here'
```

### Filter by Pipeline

```bash theme={null}
curl --request GET \
  'https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=unattended&pipelineId=3705a021-9b5f-4a3b-b6fc-27468910ffb2' \
  --header 'x-api-key: your_api_key_here'
```

## Example Response

```json theme={null}
{
  "data": [
    {
      "id": "df980fc8-b6db-4820-bf22-2969482d106d",
      "name": "Maria Rodriguez",
      "created_at": "2024-09-30T10:00:00.000Z",
      "platform": "whatsapp",
      "chat_status": "unattended",
      "waiting_time": 3600,
      "active_ticket_v2": {
        "id": "ticket-123",
        "status": "OPEN",
        "current_stage": {
          "id": "stage-456",
          "name": "Initial Contact"
        }
      },
      "assigned_agents": []
    },
    {
      "id": "880e8400-e29b-41d4-a716-446655440003",
      "name": "Carlos Silva",
      "created_at": "2024-09-30T11:30:00.000Z",
      "platform": "instagram",
      "chat_status": "unattended",
      "waiting_time": 1800,
      "active_ticket_v2": {
        "id": "ticket-789",
        "status": "OPEN",
        "current_stage": {
          "id": "stage-456",
          "name": "Initial Contact"
        }
      },
      "assigned_agents": []
    }
  ],
  "total": 15
}
```

## Common Use Cases

### 1. Display Priority Queue

```javascript theme={null}
const displayPriorityQueue = async (status = 'unattended') => {
  const response = await fetch(
    `https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=${status}`,
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const { data } = await response.json();

  console.log(`🔴 Contacts Waiting for Response (${status}):\n`);

  data.forEach((contact, index) => {
    const waitMinutes = Math.floor(contact.waiting_time / 60);
    const urgency =
      waitMinutes > 60
        ? '🔴 URGENT'
        : waitMinutes > 30
          ? '🟡 HIGH'
          : '🟢 NORMAL';

    console.log(`${index + 1}. ${contact.name}`);
    console.log(`   Waiting: ${waitMinutes} minutes ${urgency}`);
    console.log(`   Platform: ${contact.platform}`);
    console.log(
      `   Stage: ${contact.active_ticket_v2?.current_stage?.name || 'N/A'}\n`,
    );
  });

  return data;
};
```

### 2. SLA Alert System

```javascript theme={null}
const checkSLAViolations = async (slaMinutes = 30) => {
  const response = await fetch(
    'https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=unattended',
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const { data } = await response.json();

  const violations = data.filter(
    (contact) => contact.waiting_time / 60 > slaMinutes,
  );

  if (violations.length > 0) {
    console.warn(
      `⚠️ SLA VIOLATION: ${violations.length} contacts waiting > ${slaMinutes} minutes`,
    );

    violations.forEach((contact) => {
      const waitMinutes = Math.floor(contact.waiting_time / 60);
      console.warn(
        `- ${contact.name}: ${waitMinutes}m (${waitMinutes - slaMinutes}m over SLA)`,
      );
    });
  } else {
    console.log('✅ All contacts within SLA');
  }

  return violations;
};
```

### 3. Auto-Assignment Based on Wait Time

```javascript theme={null}
const autoAssignLongWaiting = async (thresholdMinutes = 15) => {
  const response = await fetch(
    'https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=unattended',
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const { data } = await response.json();

  // Find contacts waiting longer than threshold
  const longWaiting = data.filter(
    (contact) => contact.waiting_time / 60 > thresholdMinutes,
  );

  console.log(
    `Found ${longWaiting.length} contacts waiting > ${thresholdMinutes}m`,
  );

  // Auto-assign to available team member
  for (const contact of longWaiting) {
    // Get available team member
    const teamMember = await findAvailableTeamMember();

    // Assign contact
    await fetch(
      `https://api.vambe.me/api/public/contact/${contact.id}/assign-team-member/${teamMember.id}`,
      {
        method: 'POST',
        headers: {
          'x-api-key': 'your_api_key_here',
        },
      },
    );

    console.log(`Assigned ${contact.name} to ${teamMember.name}`);
  }

  return longWaiting;
};
```

### 4. Status Dashboard

```javascript theme={null}
const getStatusDashboard = async () => {
  const statuses = ['unattended', 'attended', 'ai-attended', 'ai-away'];
  const dashboard = {};

  for (const status of statuses) {
    const response = await fetch(
      `https://api.vambe.me/api/public/analytics/contacts/by-status?page=1&status=${status}`,
      {
        headers: {
          'x-api-key': 'your_api_key_here',
        },
      },
    );

    const { data, total } = await response.json();

    dashboard[status] = {
      count: total,
      averageWaitTime:
        data.reduce((sum, c) => sum + c.waiting_time, 0) / data.length / 60,
      longestWait: Math.max(...data.map((c) => c.waiting_time)) / 60,
    };
  }

  console.log('📊 Status Dashboard:', dashboard);
  return dashboard;
};
```

## Waiting Time Calculation

The `waiting_time` field is calculated as:

```
waiting_time = (current_time - last_inbound_message_time) in seconds
```

* **Unit**: Seconds
* **Sorted**: Longest waiting time first
* **Real-time**: Calculated at query time

To convert to minutes:

```javascript theme={null}
const waitMinutes = Math.floor(contact.waiting_time / 60);
```

## Pagination

* Each page returns up to 50 contacts
* Contacts sorted by waiting\_time DESC (longest wait first)
* Use `total` field to determine total matching contacts

## Error Responses

| Status Code | Description                                  |
| ----------- | -------------------------------------------- |
| 400         | Bad Request - Invalid status or parameters   |
| 401         | Unauthorized - Invalid or missing API key    |
| 500         | Internal Server Error - Something went wrong |

## Important Notes

* **Sorted by Urgency**: Longest waiting contacts appear first
* **Active Tickets**: Only shows contacts with active tickets
* **Real-time**: Waiting time calculated dynamically
* **Status Filter Required**: Must specify a status

## Related Endpoints

* [GET /api/analytics/team/snapshot/unanswered-conversations-details](/reference/analytics/get-unanswered-conversations-details) - Alternative with more filters
* [GET /api/analytics/team/snapshot/agent-distribution](/reference/analytics/get-agent-distribution) - See current workload
* [POST /api/public/contact/{aiContactId}/assign-team-member/{teamMemberId}](/reference/team-members/assign-team-member-to-contact) - Assign contacts to team members


## OpenAPI

````yaml get /api/public/analytics/contacts/by-status
openapi: 3.0.0
info:
  title: Vambe AI API
  description: Vambe AI documentation
  version: '1.0'
  contact: {}
servers:
  - url: https://api.vambe.me
    description: Production Server
security: []
tags:
  - name: Vambe AI
    description: ''
paths:
  /api/public/analytics/contacts/by-status:
    get:
      tags:
        - Analytics
      summary: Get contacts by status
      description: >-
        Returns contacts filtered by status and calculates how long they have
        been waiting (from last_inbound_message.created_at until now). Adds a
        "waiting_time" field that represents (in seconds) how long that contact
        has been waiting. Sorted by waiting_time descending (longest wait
        first).
      operationId: AnalyticsPublicController_getContactsWithUnattendedTickets
      parameters:
        - name: page
          required: true
          in: query
          description: Page number
          schema:
            example: '1'
            type: string
        - name: orderBy
          required: false
          in: query
          schema:
            enum:
              - contact_created_at
              - ticket_created_at
              - last_inbound_message
              - last_outbound_message
              - id
            type: string
        - name: channel
          required: true
          in: query
          schema:
            enum:
              - whatsapp
              - playground
              - instagram
              - webchat
              - web-whatsapp
              - messenger
              - sms
            type: string
        - name: pipelineId
          required: true
          in: query
          description: Pipeline ID
          schema:
            example: '1234567890'
            type: string
        - name: status
          required: true
          in: query
          description: Status
          schema:
            enum:
              - unattended
              - attended
              - ai-attended
              - ai-away
            type: string
        - name: x-api-key
          in: header
          description: API key
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Returns contacts with pending responses
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                      description: Contact ID
                    name:
                      type: string
                      description: Contact name
                    created_at:
                      type: string
                      format: date-time
                      description: Contact creation date

````