GET
/
api
/
public
/
contacts
Get contacts by days
curl --request GET \
  --url https://api.vambe.me/api/public/contacts \
  --header 'x-api-key: <x-api-key>'
[
  {
    "id": "df980fc8-b6db-4820-bf22-2969482d106d",
    "name": "John Doe",
    "phone": "+56912345678",
    "email": "john@example.com",
    "platform": "whatsapp",
    "last_message_at": "2024-09-30T10:00:00.000Z",
    "chat_status": "ATTENDED",
    "created_at": "2024-01-15T10:00:00.000Z"
  }
]

Overview

Retrieve contacts that had their last message within a specified number of days. This endpoint works across all communication channels (WhatsApp, Instagram, Web Chat, SMS, etc.) providing a unified view of recent contact activity. Perfect for identifying active contacts, tracking engagement, and filtering contacts by recency across your entire customer base.

Use Cases

  • Active Contacts Dashboard: Show contacts who messaged in the last 7, 30, or 90 days
  • Engagement Metrics: Track how many contacts are actively engaging
  • Re-engagement Campaigns: Find contacts who haven’t messaged recently
  • Activity Reports: Generate reports of contact activity over time
  • Cross-Channel Analytics: See all active contacts regardless of channel
  • CRM Sync: Export recently active contacts to external systems

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

ParameterTypeRequiredDescription
daysnumberYesNumber of days to filter contacts (1-365)

Response Structure

Returns an array of contact objects:
FieldTypeDescription
idstring (UUID)Unique identifier for the contact
namestringContact’s full name
phonestring | nullContact’s phone number
emailstring | nullContact’s email address
platformstringCommunication channel (whatsapp, instagram, etc.)
last_message_atstring (ISO)Timestamp of the last message sent/received
chat_statusstringCurrent chat status (UNATTENDED, ATTENDED, etc.)
created_atstring (ISO)Contact creation timestamp
client_idstring (UUID)Your organization ID
ai_customer_idstring (UUID)Associated customer profile ID
default_stage_idstring (UUID)Current pipeline stage
blockedbooleanWhether the contact is blocked
is_chat_readbooleanWhether the chat has been read by an agent

Example Request

curl --request GET \
  'https://api.vambe.ai/api/public/contacts?days=30' \
  --header 'x-api-key: your_api_key_here'

Example Response

[
  {
    "id": "df980fc8-b6db-4820-bf22-2969482d106d",
    "name": "Maria Rodriguez",
    "phone": "+56912345678",
    "email": "maria.rodriguez@example.com",
    "platform": "whatsapp",
    "last_message_at": "2024-09-30T14:25:33.000Z",
    "chat_status": "ATTENDED",
    "created_at": "2024-01-15T10:00:00.000Z",
    "client_id": "550e8400-e29b-41d4-a716-446655440000",
    "ai_customer_id": "660e8400-e29b-41d4-a716-446655440001",
    "default_stage_id": "770e8400-e29b-41d4-a716-446655440002",
    "blocked": false,
    "is_chat_read": true
  },
  {
    "id": "880e8400-e29b-41d4-a716-446655440003",
    "name": "Carlos Silva",
    "phone": "+56987654321",
    "email": null,
    "platform": "instagram",
    "last_message_at": "2024-09-29T18:10:22.000Z",
    "chat_status": "UNATTENDED",
    "created_at": "2024-03-20T09:30:00.000Z",
    "client_id": "550e8400-e29b-41d4-a716-446655440000",
    "ai_customer_id": "990e8400-e29b-41d4-a716-446655440004",
    "default_stage_id": "aa0e8400-e29b-41d4-a716-446655440005",
    "blocked": false,
    "is_chat_read": false
  }
]

Common Use Cases

1. Get Contacts from Last 7 Days

const getRecentContacts = async () => {
  const response = await fetch(
    'https://api.vambe.ai/api/public/contacts?days=7',
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const contacts = await response.json();
  console.log(`Found ${contacts.length} contacts active in the last 7 days`);

  return contacts;
};

2. Track Engagement by Channel

const getContactsByChannel = async (days) => {
  const response = await fetch(
    `https://api.vambe.ai/api/public/contacts?days=${days}`,
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const contacts = await response.json();

  // Group by platform
  const byChannel = contacts.reduce((acc, contact) => {
    const channel = contact.platform || 'unknown';
    if (!acc[channel]) acc[channel] = [];
    acc[channel].push(contact);
    return acc;
  }, {});

  console.log('Contacts by channel:', {
    whatsapp: byChannel.whatsapp?.length || 0,
    instagram: byChannel.instagram?.length || 0,
    webchat: byChannel.webchat?.length || 0,
  });

  return byChannel;
};

3. Find Unattended Contacts

const getUnattendedContacts = async (days) => {
  const response = await fetch(
    `https://api.vambe.ai/api/public/contacts?days=${days}`,
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const contacts = await response.json();

  // Filter unattended
  const unattended = contacts.filter(
    (c) => c.chat_status === 'UNATTENDED' && !c.is_chat_read,
  );

  console.log(`${unattended.length} unattended contacts need attention`);

  return unattended;
};

4. Re-engagement Campaign Data

const getContactsForReengagement = async () => {
  // Get contacts from 30-60 days ago (active before but not recently)
  const recent30 = await fetch(
    'https://api.vambe.ai/api/public/contacts?days=30',
    {
      headers: { 'x-api-key': 'your_api_key_here' },
    },
  ).then((r) => r.json());

  const recent60 = await fetch(
    'https://api.vambe.ai/api/public/contacts?days=60',
    {
      headers: { 'x-api-key': 'your_api_key_here' },
    },
  ).then((r) => r.json());

  // Contacts in 60 days but not in 30 days
  const recent30Ids = new Set(recent30.map((c) => c.id));
  const reengageTargets = recent60.filter((c) => !recent30Ids.has(c.id));

  console.log(`${reengageTargets.length} contacts for re-engagement campaign`);

  return reengageTargets;
};

5. Export to External CRM

const exportRecentContactsToCRM = async (days) => {
  const response = await fetch(
    `https://api.vambe.ai/api/public/contacts?days=${days}`,
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const contacts = await response.json();

  // Export to external CRM
  for (const contact of contacts) {
    await fetch('https://external-crm.com/api/contacts/sync', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer crm_token',
      },
      body: JSON.stringify({
        external_id: contact.id,
        name: contact.name,
        phone: contact.phone,
        email: contact.email,
        platform: contact.platform,
        last_activity: contact.last_message_at,
        status: contact.chat_status,
      }),
    });
  }

  console.log(`Exported ${contacts.length} contacts to CRM`);
};

6. Activity Dashboard

const buildActivityDashboard = async () => {
  const periods = [
    { label: 'Today', days: 1 },
    { label: 'Last 7 days', days: 7 },
    { label: 'Last 30 days', days: 30 },
    { label: 'Last 90 days', days: 90 },
  ];

  const dashboard = {};

  for (const period of periods) {
    const response = await fetch(
      `https://api.vambe.ai/api/public/contacts?days=${period.days}`,
      {
        headers: {
          'x-api-key': 'your_api_key_here',
        },
      },
    );

    const contacts = await response.json();

    dashboard[period.label] = {
      total: contacts.length,
      unattended: contacts.filter((c) => c.chat_status === 'UNATTENDED').length,
      attended: contacts.filter((c) => c.chat_status === 'ATTENDED').length,
      byChannel: contacts.reduce((acc, c) => {
        acc[c.platform] = (acc[c.platform] || 0) + 1;
        return acc;
      }, {}),
    };
  }

  console.log('Activity Dashboard:', dashboard);
  return dashboard;
};

Days Parameter

The days parameter filters contacts where last_message_at is within the specified number of days from now:
Days ValueDescriptionUse Case
1Last 24 hoursToday’s activity
7Last weekWeekly engagement report
30Last monthMonthly active contacts
90Last quarterQuarterly analysis
180Last 6 monthsSemi-annual review
365Last year (maximum allowed)Annual customer base analysis

Response Ordering

Contacts are returned ordered by last_message_at in descending order (most recent first).

Cross-Channel Support

This endpoint returns contacts from all channels:
PlatformDescription
whatsappWhatsApp Business API
web-whatsappWhatsApp Web (QR)
instagramInstagram Direct Messages
webchatWeb chat widget
smsSMS messages
messengerFacebook Messenger
tiktokTikTok Direct Messages
voiceVoice calls
playgroundTest/playground channel

Error Responses

Status CodeDescription
400Bad Request - Invalid days parameter (must be 1-365)
401Unauthorized - Invalid or missing API key
500Internal Server Error - Something went wrong

Important Notes

  • Days Range: Must be between 1 and 365 days
  • Null Values: Some fields like email or phone may be null
  • Performance: Response time increases with larger days values
  • All Channels: Unlike the deprecated WhatsApp-specific endpoint, this returns contacts from ALL channels
  • Contact Count: No pagination - returns all contacts matching the criteria

Performance Considerations

  • Cache Results: Consider caching responses for frequently used days values
  • Large Datasets: For days values > 90, expect larger response sizes
  • Rate Limiting: Be mindful of rate limits when making frequent requests

Comparison with Deprecated Endpoint

FeatureNew Endpoint (This)Deprecated Endpoint
Path/api/public/contacts/api/public/whatsapp/contact/contacts
ChannelsAll channelsWhatsApp only
ResponseAI Contact objectsWhatsApp Contact objects
OrderingBy last_message_at DESCNot specified
Future Supportβœ… Active development❌ Deprecated

Best Practices

1. Choose Appropriate Days Range

// Good: Specific use case
const getWeeklyActive = () => fetch('...?days=7');
const getMonthlyActive = () => fetch('...?days=30');

// Avoid: Unnecessarily large range
const getAll = () => fetch('...?days=365'); // Only if you need a full year

2. Handle Empty Results

const contacts = await fetch('...?days=7').then((r) => r.json());

if (contacts.length === 0) {
  console.log('No contacts in the last 7 days');
} else {
  console.log(`Found ${contacts.length} active contacts`);
}

3. Filter on Client Side

const contacts = await fetch('...?days=30').then((r) => r.json());

// Filter by platform
const whatsappContacts = contacts.filter((c) => c.platform === 'whatsapp');

// Filter by status
const unread = contacts.filter((c) => !c.is_chat_read);

// Filter by date range
const thisWeek = contacts.filter((c) => {
  const msgDate = new Date(c.last_message_at);
  const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
  return msgDate > sevenDaysAgo;
});

Headers

x-api-key
string
required

API key needed to authorize the request

Query Parameters

days
number
required

Number of days to filter contacts (1-365)

Required range: 1 <= x <= 365
Example:

30

Response

Contacts retrieved successfully.

id
string
Example:

"df980fc8-b6db-4820-bf22-2969482d106d"

name
string
Example:

"John Doe"

phone
string
Example:

"+56912345678"

email
string
Example:

"john@example.com"

platform
string
Example:

"whatsapp"

last_message_at
string
Example:

"2024-09-30T10:00:00.000Z"

chat_status
string
Example:

"ATTENDED"

created_at
string
Example:

"2024-01-15T10:00:00.000Z"