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:

http
Authorization: Bearer YOUR_API_KEY

Or:

http
X-API-Key: YOUR_API_KEY

Create API keys in SettingsAPI Keys with appropriate permissions.


Import Historical Data

Push historical contact center data for forecasting.

POST/api/v1/import/historicalAuth: API Key

Import historical contact data.

Required Permission: import:historical

Request Body:

json
{
"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"
}
]
}
ParameterTypeRequiredDescription
datestringRequiredDate (YYYY-MM-DD)
intervalstringRequiredInterval start time (HH:MM)
volumenumberRequiredNumber of contacts
ahtnumberRequiredAverage handle time in seconds
queuestringOptionalQueue or skill name
channelstringOptionalContact channel (voice, chat, email)

Response (201):

json
{
"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.

POST/api/v1/import/employeesAuth: API Key

Import or sync employees.

Required Permission: import:employees

Request Body:

json
{
"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
}
ParameterTypeRequiredDescription
emailstringRequiredEmployee email (unique identifier)
firstNamestringRequiredFirst name
lastNamestringRequiredLast name
employeeIdstringOptionalExternal employee ID
teamstringOptionalTeam name (created if doesn't exist)
rolestringOptionalRole: "admin", "supervisor", "agent"
skillsarrayOptionalSkill names (created if don't exist)
activebooleanOptionalActive status
updateExistingbooleanOptionalUpdate if email exists (default false)

Response (201):

json
{
"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.

POST/api/v1/import/agent-statesAuth: API Key

Push real-time agent state changes.

Required Permission: import:agent-states

Request Body:

json
{
"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"
}
]
}
ParameterTypeRequiredDescription
agentIdstringRequiredAgent identifier (email or employee ID)
statestringRequiredNew state (see valid states below)
timestampstringRequiredISO 8601 timestamp
queuestringOptionalQueue or skill name
acdStateCodestringOptionalOriginal 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):

json
{
"success": true,
"processed": 2,
"skipped": 0,
"errors": []
}

Integration Examples

cURL Example

bash
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

javascript
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

python
import requests
from datetime import datetime
response = 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:

json
{
"error": "Rate limit exceeded",
"retryAfter": 30
}

Wait the specified seconds before retrying.


Error Handling

Partial Success

Some records may fail while others succeed:

json
{
"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

  1. Batch requests: Send multiple records per request (up to limits)
  2. Handle errors: Process partial successes and retry failures
  3. Use timestamps: Include accurate timestamps for agent states
  4. Map states correctly: Ensure ACD states map to valid ezyWFM states
  5. Monitor usage: Check API key usage in Settings
  6. Rotate keys: Periodically rotate API keys for security