Contacts
Contacts & Groups Management
Organize your recipients with contacts and groups to efficiently manage and target your messaging campaigns.
Overview
Contacts: Individual recipients with contact information (name, email, phone, company, tags)
Groups: Logical collections of contacts for targeted messaging (e.g., "VIP Customers", "Newsletter Subscribers")
Use Cases:
- Send targeted campaigns to specific groups
- Organize contacts by category, location, or custom criteria
- Track and manage your audience database
- Enable personalized bulk messaging
Contacts
Create Contact
Add a new contact to your organization.
Endpoint: POST https://api.notifyhub.com/contacts
Authentication: Required
Request:
{
"name": "John Doe",
"email": "john.doe@acme.com",
"phone": "712345678",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip", "customer"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"]
}Field Descriptions:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Contact's full name |
| email | string | No | Email address (required for email channel) |
| phone | string | No | Phone number without country code (required for SMS/WhatsApp) |
| countryCode | string | No | Phone country code (e.g., "+254") |
| organization | string | No | Contact's company/organization name |
| tags | array | No | Custom tags for filtering/categorization |
| groups | array | No | Array of group IDs this contact belongs to |
Note: At least one of email or phone is required for sending messages.
Response (201 Created):
{
"_id": "6978abcd1234567890abcdef",
"name": "John Doe",
"email": "john.doe@acme.com",
"phone": "712345678",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip", "customer"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"NotifyhubOrganization": "695cc3b0212740bd1dba40d2",
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-26T10:15:00.000Z"
}Example:
curl -X POST https://api.notifyhub.com/contacts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john.doe@acme.com",
"phone": "712345678",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"]
}'List All Contacts
Retrieve all contacts in your organization.
Endpoint: GET https://api.notifyhub.com/contacts
Authentication: Required
Response (200 OK):
[
{
"_id": "6978abcd1234567890abcdef",
"name": "John Doe",
"email": "john.doe@acme.com",
"phone": "712345678",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-26T10:15:00.000Z"
},
{
"_id": "6978efgh1234567890ghijkl",
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "723456789",
"countryCode": "+254",
"organization": "Example Inc",
"tags": ["customer"],
"groups": [],
"createdAt": "2026-01-25T14:30:00.000Z",
"updatedAt": "2026-01-25T14:30:00.000Z"
}
]Example:
curl -X GET https://api.notifyhub.com/contacts \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch('https://api.notifyhub.com/contacts', {
headers: { 'Authorization': `Bearer ${token}` }
});
const contacts = await response.json();Get Contact by ID
Retrieve a specific contact.
Endpoint: GET https://api.notifyhub.com/contacts/:id
Authentication: Required
Path Parameters:
id(required): Contact ID
Response (200 OK):
{
"_id": "6978abcd1234567890abcdef",
"name": "John Doe",
"email": "john.doe@acme.com",
"phone": "712345678",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip", "customer"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7"],
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-26T10:15:00.000Z"
}Example:
curl -X GET https://api.notifyhub.com/contacts/6978abcd1234567890abcdef \
-H "Authorization: Bearer YOUR_TOKEN"Update Contact
Update contact information.
Endpoint: PUT https://api.notifyhub.com/contacts/:id
Authentication: Required
Path Parameters:
id(required): Contact ID
Request (partial update - send only fields to change):
{
"name": "John Updated Doe",
"email": "john.updated@acme.com",
"phone": "723456789",
"tags": ["vip", "premium"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7", "60d5f8e4c3f1a2b3c4d5e6f8"]
}Response (200 OK):
{
"_id": "6978abcd1234567890abcdef",
"name": "John Updated Doe",
"email": "john.updated@acme.com",
"phone": "723456789",
"countryCode": "+254",
"organization": "Acme Corp",
"tags": ["vip", "premium"],
"groups": ["60d5f8e4c3f1a2b3c4d5e6f7", "60d5f8e4c3f1a2b3c4d5e6f8"],
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-27T09:30:00.000Z"
}Example:
curl -X PUT https://api.notifyhub.com/contacts/6978abcd1234567890abcdef \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "John Updated Doe",
"tags": ["vip", "premium"]
}'Delete Contact
Permanently delete a contact.
Endpoint: DELETE https://api.notifyhub.com/contacts/:id
Authentication: Required
Path Parameters:
id(required): Contact ID
Response (200 OK):
{
"message": "Contact deleted successfully"
}Example:
curl -X DELETE https://api.notifyhub.com/contacts/6978abcd1234567890abcdef \
-H "Authorization: Bearer YOUR_TOKEN"Note: Deleting a contact does not remove them from groups or delete associated message logs.
Groups
Create Group
Create a new contact group.
Endpoint: POST https://api.notifyhub.com/groups
Authentication: Required
Request:
{
"name": "VIP Customers",
"description": "High-value clients requiring priority support",
"color": "bg-blue-500/10 text-blue-500 border-blue-500/20"
}Field Descriptions:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | Group name (must be unique within organization) |
| description | string | No | Group description/purpose |
| color | string | Yes | UI color theme (Tailwind CSS classes) |
Response (201 Created):
{
"_id": "6978abcd1234567890abcdef",
"name": "VIP Customers",
"description": "High-value clients requiring priority support",
"color": "bg-blue-500/10 text-blue-500 border-blue-500/20",
"organization": "695cc3b0212740bd1dba40d2",
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-26T10:15:00.000Z"
}Example:
curl -X POST https://api.notifyhub.com/groups \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP Customers",
"description": "High-value clients",
"color": "bg-blue-500/10 text-blue-500 border-blue-500/20"
}'Color Options (recommended Tailwind classes):
const colors = [
'bg-blue-500/10 text-blue-500 border-blue-500/20',
'bg-green-500/10 text-green-500 border-green-500/20',
'bg-purple-500/10 text-purple-500 border-purple-500/20',
'bg-red-500/10 text-red-500 border-red-500/20',
'bg-orange-500/10 text-orange-500 border-orange-500/20',
'bg-pink-500/10 text-pink-500 border-pink-500/20',
'bg-indigo-500/10 text-indigo-500 border-indigo-500/20',
'bg-teal-500/10 text-teal-500 border-teal-500/20'
];List All Groups
Retrieve all groups in your organization.
Endpoint: GET https://api.notifyhub.com/groups
Authentication: Required
Response (200 OK):
[
{
"_id": "6978abcd1234567890abcdef",
"name": "VIP Customers",
"description": "High-value clients",
"color": "bg-blue-500/10 text-blue-500 border-blue-500/20",
"organization": "695cc3b0212740bd1dba40d2",
"createdAt": "2026-01-26T10:15:00.000Z",
"updatedAt": "2026-01-26T10:15:00.000Z"
},
{
"_id": "6978efgh1234567890ghijkl",
"name": "Newsletter Subscribers",
"description": "Monthly newsletter recipients",
"color": "bg-green-500/10 text-green-500 border-green-500/20",
"organization": "695cc3b0212740bd1dba40d2",
"createdAt": "2026-01-25T14:30:00.000Z",
"updatedAt": "2026-01-25T14:30:00.000Z"
}
]Example:
curl -X GET https://api.notifyhub.com/groups \
-H "Authorization: Bearer YOUR_TOKEN"Delete Group
Permanently delete a group.
Endpoint: DELETE https://api.notifyhub.com/groups/:id
Authentication: Required
Path Parameters:
id(required): Group ID
Response (200 OK):
{
"message": "Group deleted successfully"
}Example:
curl -X DELETE https://api.notifyhub.com/groups/6978abcd1234567890abcdef \
-H "Authorization: Bearer YOUR_TOKEN"Note: Deleting a group does not delete the contacts in that group. Contacts will simply no longer be associated with the deleted group.
Managing Group Membership
Contacts can belong to multiple groups. Membership is managed through the contacts endpoints.
Add Contact to Group
Update the contact's groups array to include the group ID.
curl -X PUT https://api.notifyhub.com/contacts/CONTACT_ID \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groups": ["GROUP_ID_1", "GROUP_ID_2"]
}'Remove Contact from Group
Update the contact's groups array to exclude the group ID.
curl -X PUT https://api.notifyhub.com/contacts/CONTACT_ID \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groups": ["GROUP_ID_1"]
}'Get Contacts in a Group
Filter contacts by group using your application logic:
// 1. Get all contacts
const contacts = await fetch('https://api.notifyhub.com/contacts', {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
// 2. Filter by group ID
const groupId = '6978abcd1234567890abcdef';
const groupContacts = contacts.filter(contact =>
contact.groups.includes(groupId)
);Bulk Operations
Bulk Create Contacts
Create multiple contacts in a loop (future: dedicated bulk endpoint).
async function bulkCreateContacts(contacts, token) {
const results = [];
for (const contact of contacts) {
try {
const response = await fetch('https://api.notifyhub.com/contacts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(contact)
});
const result = await response.json();
results.push({ success: true, contact: result });
} catch (error) {
results.push({ success: false, error: error.message });
}
}
return results;
}
// Usage
const contactsToCreate = [
{ name: 'John Doe', email: 'john@example.com', phone: '712345678', countryCode: '+254' },
{ name: 'Jane Smith', email: 'jane@example.com', phone: '723456789', countryCode: '+254' }
];
const results = await bulkCreateContacts(contactsToCreate, token);Import from CSV
const csv = require('csv-parser');
const fs = require('fs');
async function importContactsFromCSV(filePath, token) {
const contacts = [];
// Read CSV
await new Promise((resolve) => {
fs.createReadStream(filePath)
.pipe(csv())
.on('data', (row) => {
contacts.push({
name: row.name,
email: row.email,
phone: row.phone,
countryCode: row.countryCode || '+254',
organization: row.company,
tags: row.tags ? row.tags.split(',') : []
});
})
.on('end', resolve);
});
// Create contacts
return await bulkCreateContacts(contacts, token);
}
// Usage
await importContactsFromCSV('contacts.csv', token);CSV Format:
name,email,phone,countryCode,company,tags
John Doe,john@example.com,712345678,+254,Acme Corp,vip,customer
Jane Smith,jane@example.com,723456789,+254,Example Inc,customerBest Practices
1. Data Quality
// Validate before creating
function validateContact(contact) {
const errors = [];
if (!contact.name) {
errors.push('Name is required');
}
if (!contact.email && !contact.phone) {
errors.push('At least email or phone is required');
}
if (contact.email && !isValidEmail(contact.email)) {
errors.push('Invalid email format');
}
if (contact.phone && !isValidPhone(contact.phone)) {
errors.push('Invalid phone format');
}
return errors.length === 0 ? null : errors;
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function isValidPhone(phone) {
return /^\d{9,15}$/.test(phone);
}2. Tag Strategy
Use consistent, lowercase tags for easier filtering:
const tagCategories = {
status: ['active', 'inactive', 'pending'],
tier: ['vip', 'premium', 'standard'],
source: ['website', 'referral', 'event'],
engagement: ['high', 'medium', 'low']
};
// Good
{ tags: ['vip', 'active', 'website'] }
// Avoid
{ tags: ['VIP Customer', 'Very Active', 'From Website'] }3. Group Organization
Create logical, non-overlapping groups:
// Good structure
const groups = [
{ name: 'VIP Customers', description: 'Top 10% by revenue' },
{ name: 'Newsletter Subscribers', description: 'Opted in for monthly updates' },
{ name: 'Trial Users', description: 'Active free trial users' },
{ name: 'Support Tickets', description: 'Open support cases' }
];
// Avoid overlapping or vague groups
// Bad: 'Important Customers', 'Other Customers', 'Miscellaneous'4. Deduplication
Check for duplicates before creating:
async function createContactSafely(contact, token) {
// 1. Get existing contacts
const existing = await fetch('https://api.notifyhub.com/contacts', {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
// 2. Check for duplicates
const duplicate = existing.find(c =>
c.email === contact.email ||
(c.phone === contact.phone && c.countryCode === contact.countryCode)
);
if (duplicate) {
console.log('Contact already exists:', duplicate._id);
return duplicate;
}
// 3. Create new contact
return await fetch('https://api.notifyhub.com/contacts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(contact)
}).then(r => r.json());
}Error Handling
Common Errors
400 Bad Request - Missing Required Fields:
{
"statusCode": 400,
"message": "name is required",
"error": "Bad Request"
}400 Bad Request - Duplicate Group Name:
{
"statusCode": 400,
"message": "Group name already exists in this organization",
"error": "Bad Request"
}404 Not Found:
{
"statusCode": 404,
"message": "Contact not found",
"error": "Not Found"
}Error Handling Example
async function safeCreateContact(contact, token) {
try {
const response = await fetch('https://api.notifyhub.com/contacts', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(contact)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return await response.json();
} catch (error) {
console.error('Failed to create contact:', error.message);
return null;
}
}Next Steps:
- Send Messages - Use contacts in SMS, Email, WhatsApp
- Campaigns - Send bulk messages to groups
- API Reference - Complete endpoint documentation