External Integration API
Server-to-server integration endpoints for pushing data from external systems. These endpoints use API key authentication.
Authentication
All v1 endpoints require API key authentication:
Authorization: Bearer YOUR_API_KEYOr:
X-API-Key: YOUR_API_KEYCreate API keys in Settings → API Keys with appropriate permissions.
Import Historical Data
Push historical contact center data for forecasting.
/api/v1/import/historicalAuth: API KeyImport historical contact data.
Required Permission: import:historical
Request Body:
{ "data": [ { "date": "2026-01-15", "interval": "08:00", "volume": 45, "aht": 180, "queue": "sales", "channel": "voice" }, { "date": "2026-01-15", "interval": "08:30", "volume": 52, "aht": 175, "queue": "sales", "channel": "voice" } ]}| Parameter | Type | Required | Description |
|---|---|---|---|
date | string | Required | Date (YYYY-MM-DD) |
interval | string | Required | Interval start time (HH:MM) |
volume | number | Required | Number of contacts |
aht | number | Required | Average handle time in seconds |
queue | string | Optional | Queue or skill name |
channel | string | Optional | Contact channel (voice, chat, email) |
Response (201):
{ "success": true, "imported": 48, "skipped": 0, "errors": []}Import data in batches of up to 10,000 records per request.
Import Employees
Sync employees from your HRIS or identity provider.
/api/v1/import/employeesAuth: API KeyImport or sync employees.
Required Permission: import:employees
Request Body:
{ "data": [ { "email": "john.doe@company.com", "firstName": "John", "lastName": "Doe", "employeeId": "EMP001", "team": "Support", "role": "agent", "skills": ["billing", "technical"], "active": true }, { "email": "jane.smith@company.com", "firstName": "Jane", "lastName": "Smith", "employeeId": "EMP002", "team": "Sales", "role": "supervisor", "skills": ["sales"], "active": true } ], "updateExisting": false}| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Required | Employee email (unique identifier) |
firstName | string | Required | First name |
lastName | string | Required | Last name |
employeeId | string | Optional | External employee ID |
team | string | Optional | Team name (created if doesn't exist) |
role | string | Optional | Role: "admin", "supervisor", "agent" |
skills | array | Optional | Skill names (created if don't exist) |
active | boolean | Optional | Active status |
updateExisting | boolean | Optional | Update if email exists (default false) |
Response (201):
{ "success": true, "created": 5, "updated": 2, "skipped": 0, "errors": []}With updateExisting: false, existing employees (matched by email) are skipped.
Import Agent States
Push real-time agent state changes from your ACD.
/api/v1/import/agent-statesAuth: API KeyPush real-time agent state changes.
Required Permission: import:agent-states
Request Body:
{ "data": [ { "agentId": "john.doe@company.com", "state": "on_call", "timestamp": "2026-01-29T08:30:00Z", "queue": "sales", "acdStateCode": "TALKING" }, { "agentId": "jane.smith@company.com", "state": "available", "timestamp": "2026-01-29T08:30:05Z", "queue": "support" } ]}| Parameter | Type | Required | Description |
|---|---|---|---|
agentId | string | Required | Agent identifier (email or employee ID) |
state | string | Required | New state (see valid states below) |
timestamp | string | Required | ISO 8601 timestamp |
queue | string | Optional | Queue or skill name |
acdStateCode | string | Optional | Original ACD state code for mapping |
Valid States:
| State | Description |
|-------|-------------|
| available | Ready to take contacts |
| on_call | Handling a contact |
| after_call_work | Post-call tasks |
| break | On break |
| lunch | On lunch |
| meeting | In a meeting |
| training | In training |
| offline | Not logged in |
| unavailable | Logged in but not available |
Response (201):
{ "success": true, "processed": 2, "skipped": 0, "errors": []}Integration Examples
cURL Example
curl -X POST https://your-domain.com/api/v1/import/agent-states \ -H "Authorization: Bearer nwfm_your_api_key_here" \ -H "Content-Type: application/json" \ -d '{ "data": [{ "agentId": "john.doe@company.com", "state": "on_call", "timestamp": "2026-01-29T08:30:00Z" }] }'Node.js Example
const response = await fetch('https://your-domain.com/api/v1/import/agent-states', { method: 'POST', headers: { 'Authorization': 'Bearer nwfm_your_api_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ data: [{ agentId: 'john.doe@company.com', state: 'on_call', timestamp: new Date().toISOString(), }] }),});const result = await response.json();console.log(result);Python Example
import requestsfrom datetime import datetimeresponse = requests.post( 'https://your-domain.com/api/v1/import/agent-states', headers={ 'Authorization': 'Bearer nwfm_your_api_key_here', 'Content-Type': 'application/json', }, json={ 'data': [{ 'agentId': 'john.doe@company.com', 'state': 'on_call', 'timestamp': datetime.utcnow().isoformat() + 'Z', }] })print(response.json())Rate Limits
External API endpoints are rate limited to 1,000 requests per minute per API key.
When rate limited, you'll receive:
{ "error": "Rate limit exceeded", "retryAfter": 30}Wait the specified seconds before retrying.
Error Handling
Partial Success
Some records may fail while others succeed:
{ "success": true, "processed": 95, "skipped": 3, "errors": [ { "index": 12, "error": "Invalid email format", "data": { "email": "invalid-email" } }, { "index": 45, "error": "Unknown state: CUSTOM_STATE", "data": { "agentId": "agent@example.com" } } ]}Common Errors
| Error | Cause | Solution | |-------|-------|----------| | 401 Unauthorized | Invalid or missing API key | Check API key is correct | | 403 Forbidden | Missing permission | Add required permission to key | | 429 Too Many Requests | Rate limited | Wait and retry | | 400 Validation Error | Invalid data format | Check request body format |
Best Practices
- Batch requests: Send multiple records per request (up to limits)
- Handle errors: Process partial successes and retry failures
- Use timestamps: Include accurate timestamps for agent states
- Map states correctly: Ensure ACD states map to valid ezyWFM states
- Monitor usage: Check API key usage in Settings
- Rotate keys: Periodically rotate API keys for security