Aller au contenu principal

Contacts API

The Contacts API allows you to manage customer contacts and leads in your ISAO system. You can list, create, update, and search contacts programmatically.

📋 Table of Contents

🔐 Authentication

All contacts endpoints require the contacts:read or contacts:write permissions:

  • Read operations: contacts:read permission
  • Write operations: contacts:write permission
Authorization: Bearer YOUR_API_KEY

🔗 Endpoints Overview

MethodEndpointPermissionDescription
GET/contactscontacts:readList all contacts with pagination
GET/contacts/:idcontacts:readGet specific contact by ID
POST/contactscontacts:writeCreate new contact
PUT/contacts/:idcontacts:writeUpdate existing contact

Base URL: https://staging.isao.io/api/external

📑 List Contacts

Retrieve a paginated list of contacts from your company.

Request

GET /contacts

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number (minimum: 1)
limitinteger50Items per page (maximum: 200)
searchstring-Search in name, email, or phone number
createdSincestring-ISO 8601 date, contacts created after this date
updatedSincestring-ISO 8601 date, contacts updated after this date

Example Request

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?page=1&limit=10&search=john"

Response

{
"success": true,
"data": [
{
"id": "contact_123",
"name": "John Smith",
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+33123456789",
"email": "john.smith@example.com",
"position": "CEO",
"currentCompany": "Tech Corp",
"industrySector": "Technology",
"city": "Paris",
"country": "France",
"tags": ["vip", "enterprise"],
"createdAt": "2024-11-01T10:30:00.000Z",
"updatedAt": "2024-11-08T09:15:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
}
}

👤 Get Contact by ID

Retrieve a specific contact by its ID.

Request

GET /contacts/:id

Example Request

curl -H "Authorization: Bearer YOUR_API_KEY" \
https://staging.isao.io/api/external/contacts/contact_123

Response

{
"success": true,
"data": {
"id": "contact_123",
"name": "John Smith",
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+33123456789",
"email": "john.smith@example.com",
"position": "CEO",
"currentCompany": "Tech Corp",
"industrySector": "Technology",
"city": "Paris",
"country": "France",
"tags": ["vip", "enterprise"],
"createdAt": "2024-11-01T10:30:00.000Z",
"updatedAt": "2024-11-08T09:15:00.000Z"
}
}

➕ Create Contact

Create a new contact in your system.

Request

POST /contacts
Content-Type: application/json

Required Fields

FieldTypeDescription
namestringFull name of the contact (max 255 chars)
phoneNumberstringPhone number (required, must be unique)

Optional Fields

FieldTypeDescription
firstNamestringFirst name (max 100 chars)
lastNamestringLast name (max 100 chars)
emailstringEmail address (valid email format)
positionstringJob title or position (max 100 chars)
currentCompanystringCurrent company (max 255 chars)
industrySectorstringIndustry sector (max 100 chars)
citystringCity (max 100 chars)
countrystringCountry (max 100 chars)
tagsarrayArray of strings for categorization

Example Request

curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Doe",
"firstName": "Jane",
"lastName": "Doe",
"phoneNumber": "+33987654321",
"email": "jane.doe@example.com",
"position": "Marketing Manager",
"currentCompany": "Marketing Pro",
"industrySector": "Marketing",
"city": "Lyon",
"country": "France",
"tags": ["lead", "marketing"]
}' \
https://staging.isao.io/api/external/contacts

Success Response (201 Created)

{
"success": true,
"data": {
"id": "contact_456",
"name": "Jane Doe",
"firstName": "Jane",
"lastName": "Doe",
"phoneNumber": "+33987654321",
"email": "jane.doe@example.com",
"position": "Marketing Manager",
"currentCompany": "Marketing Pro",
"industrySector": "Marketing",
"city": "Lyon",
"country": "France",
"tags": ["lead", "marketing"],
"createdAt": "2024-11-08T10:30:00.000Z",
"updatedAt": "2024-11-08T10:30:00.000Z"
}
}

Error Response (409 Conflict)

If a contact with the same phone number already exists:

{
"success": false,
"error": "Contact with this phone number already exists",
"existingContactId": "contact_123"
}

✏️ Update Contact

Update an existing contact's information.

Request

PUT /contacts/:id
Content-Type: application/json

Example Request

curl -X PUT \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"position": "Senior Marketing Manager",
"city": "Marseille",
"tags": ["lead", "marketing", "senior"]
}' \
https://staging.isao.io/api/external/contacts/contact_456

Response

{
"success": true,
"data": {
"id": "contact_456",
"name": "Jane Doe",
"firstName": "Jane",
"lastName": "Doe",
"phoneNumber": "+33987654321",
"email": "jane.doe@example.com",
"position": "Senior Marketing Manager",
"currentCompany": "Marketing Pro",
"industrySector": "Marketing",
"city": "Marseille",
"country": "France",
"tags": ["lead", "marketing", "senior"],
"createdAt": "2024-11-08T10:30:00.000Z",
"updatedAt": "2024-11-08T11:45:00.000Z"
}
}

🔍 Search and Filtering

The contacts API provides powerful search and filtering capabilities.

Search by Text

Search across name, email, and phone number fields:

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?search=jane"

Filter by Creation Date

Get contacts created since a specific date:

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?createdSince=2024-11-01T00:00:00.000Z"

Filter by Update Date

Get contacts updated since a specific date:

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?updatedSince=2024-11-07T00:00:00.000Z"

Pagination

Navigate through large datasets:

# Get page 2 with 25 items per page
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?page=2&limit=25"

Combined Filtering

Combine multiple filters:

curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://staging.isao.io/api/external/contacts?search=manager&createdSince=2024-11-01T00:00:00.000Z&limit=20"

❌ Error Handling

Common Error Responses

401 Unauthorized

{
"success": false,
"error": "API key required in Authorization header",
"message": "Please provide a valid API key in the format: Authorization: Bearer YOUR_API_KEY"
}

403 Forbidden

{
"success": false,
"error": "Permission denied: contacts:read required",
"message": "This API key does not have the required permission: contacts:read",
"requiredPermission": "contacts:read",
"availablePermissions": ["webhooks:write"]
}

404 Not Found

{
"success": false,
"error": "Contact not found"
}

409 Conflict

{
"success": false,
"error": "Contact with this phone number already exists",
"existingContactId": "contact_123"
}

422 Validation Error

{
"success": false,
"error": "Validation failed",
"details": {
"phoneNumber": "Phone number is required",
"email": "Invalid email format"
}
}

💻 Code Examples

JavaScript/Node.js

const axios = require('axios');

class ContactsAPI {
constructor(apiKey) {
this.client = axios.create({
baseURL: 'https://staging.isao.io/api/external',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
}

// List all contacts with pagination
async listContacts(options = {}) {
const params = {
page: options.page || 1,
limit: options.limit || 50,
search: options.search,
createdSince: options.createdSince,
updatedSince: options.updatedSince
};

const response = await this.client.get('/contacts', { params });
return response.data;
}

// Get contact by ID
async getContact(contactId) {
const response = await this.client.get(`/contacts/${contactId}`);
return response.data;
}

// Create new contact
async createContact(contactData) {
const response = await this.client.post('/contacts', contactData);
return response.data;
}

// Update contact
async updateContact(contactId, updateData) {
const response = await this.client.put(`/contacts/${contactId}`, updateData);
return response.data;
}

// Search contacts
async searchContacts(searchTerm, limit = 50) {
return this.listContacts({ search: searchTerm, limit });
}
}

// Usage example
const contactsAPI = new ContactsAPI(process.env.ISAO_API_KEY);

async function example() {
try {
// Create a contact
const newContact = await contactsAPI.createContact({
name: "Alice Johnson",
phoneNumber: "+33111222333",
email: "alice@example.com",
position: "Developer",
tags: ["developer", "new"]
});
console.log('Created contact:', newContact);

// List contacts
const contacts = await contactsAPI.listContacts({ page: 1, limit: 10 });
console.log('Contacts:', contacts);

// Search contacts
const searchResults = await contactsAPI.searchContacts("alice");
console.log('Search results:', searchResults);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}

Python

import requests
from typing import Optional, Dict, List

class ContactsAPI:
def __init__(self, api_key: str):
self.base_url = "https://staging.isao.io/api/external"
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

def list_contacts(self, page: int = 1, limit: int = 50,
search: Optional[str] = None,
created_since: Optional[str] = None,
updated_since: Optional[str] = None) -> Dict:
params = {
"page": page,
"limit": limit,
"search": search,
"createdSince": created_since,
"updatedSince": updated_since
}
# Remove None values
params = {k: v for k, v in params.items() if v is not None}

response = requests.get(f"{self.base_url}/contacts",
headers=self.headers, params=params)
response.raise_for_status()
return response.json()

def get_contact(self, contact_id: str) -> Dict:
response = requests.get(f"{self.base_url}/contacts/{contact_id}",
headers=self.headers)
response.raise_for_status()
return response.json()

def create_contact(self, contact_data: Dict) -> Dict:
response = requests.post(f"{self.base_url}/contacts",
json=contact_data, headers=self.headers)
response.raise_for_status()
return response.json()

def update_contact(self, contact_id: str, update_data: Dict) -> Dict:
response = requests.put(f"{self.base_url}/contacts/{contact_id}",
json=update_data, headers=self.headers)
response.raise_for_status()
return response.json()

def search_contacts(self, search_term: str, limit: int = 50) -> Dict:
return self.list_contacts(search=search_term, limit=limit)

# Usage example
import os

contacts_api = ContactsAPI(os.getenv("ISAO_API_KEY"))

try:
# Create a contact
new_contact = contacts_api.create_contact({
"name": "Bob Wilson",
"phoneNumber": "+33444555666",
"email": "bob@example.com",
"position": "Designer",
"tags": ["designer", "creative"]
})
print("Created contact:", new_contact)

# List contacts
contacts = contacts_api.list_contacts(page=1, limit=10)
print(f"Found {contacts['meta']['total']} contacts")

# Search contacts
search_results = contacts_api.search_contacts("bob")
print("Search results:", search_results)

except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e.response.status_code}")
print(f"Error details: {e.response.json()}")

PHP

<?php

class ContactsAPI {
private $baseUrl = 'https://staging.isao.io/api/external';
private $headers;

public function __construct($apiKey) {
$this->headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
];
}

private function makeRequest($method, $endpoint, $data = null, $params = []) {
$url = $this->baseUrl . $endpoint;
if (!empty($params)) {
$url .= '?' . http_build_query(array_filter($params));
}

$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $this->headers,
]);

if ($data) {
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
}

$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

$result = json_decode($response, true);

if ($httpCode >= 400) {
throw new Exception("API Error ({$httpCode}): " . ($result['error'] ?? 'Unknown error'));
}

return $result;
}

public function listContacts($options = []) {
$params = [
'page' => $options['page'] ?? 1,
'limit' => $options['limit'] ?? 50,
'search' => $options['search'] ?? null,
'createdSince' => $options['createdSince'] ?? null,
'updatedSince' => $options['updatedSince'] ?? null
];

return $this->makeRequest('GET', '/contacts', null, $params);
}

public function getContact($contactId) {
return $this->makeRequest('GET', "/contacts/{$contactId}");
}

public function createContact($contactData) {
return $this->makeRequest('POST', '/contacts', $contactData);
}

public function updateContact($contactId, $updateData) {
return $this->makeRequest('PUT', "/contacts/{$contactId}", $updateData);
}

public function searchContacts($searchTerm, $limit = 50) {
return $this->listContacts(['search' => $searchTerm, 'limit' => $limit]);
}
}

// Usage example
try {
$contactsAPI = new ContactsAPI(getenv('ISAO_API_KEY'));

// Create a contact
$newContact = $contactsAPI->createContact([
'name' => 'Charlie Brown',
'phoneNumber' => '+33777888999',
'email' => 'charlie@example.com',
'position' => 'Manager',
'tags' => ['manager', 'leadership']
]);
echo "Created contact: " . json_encode($newContact) . "\n";

// List contacts
$contacts = $contactsAPI->listContacts(['page' => 1, 'limit' => 10]);
echo "Found " . $contacts['meta']['total'] . " contacts\n";

// Search contacts
$searchResults = $contactsAPI->searchContacts('charlie');
echo "Search results: " . json_encode($searchResults) . "\n";

} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>

✅ Best Practices

  1. Validate phone numbers before sending to avoid conflicts
  2. Use pagination when fetching large datasets
  3. Implement search to help users find contacts quickly
  4. Handle duplicate contacts gracefully with proper error handling
  5. Use tags for categorization and filtering
  6. Set up webhooks to get real-time contact updates