Read Agent States¶
This guide explains how to read contact-center agent state change history from the Portal API — the same events the queues app writes when an agent becomes idle, on a call, in wrap-up, on DND, and so on.
Use this when you need a timeline of state transitions for one or more agents (compliance, workforce tooling, or custom dashboards).
flowchart LR
QueuesApp[Queues app] -->|write fonouc_log| CouchDB[(Account month DB)]
App[Your app] -->|GET activity/events| PortalAPI["Portal API :9443"]
PortalAPI -->|all_agent_events view| CouchDB
Note
This endpoint returns historical state-change events, not the agent's live status on the softphone. For real-time updates, see Contact Center Websocket events.
Prerequisites¶
| Requirement | Notes |
|---|---|
| Account with Contact Center / queues enabled | State logs are written when agents are active on queues |
HTTPS access to the portal API (https://{{ domain }}:9443) |
|
| API key or admin JWT | Same auth model as other /api/v2/reports/... endpoints |
Agent user_id (optional) |
Needed only if you filter the response to one user |
Authentication¶
Required headers:
X-API-Key: <your_api_key>
X-Account-ID: <your_account_id>
Base URL pattern:
https://{{ domain }}:9443/api/v2
Endpoint¶
GET /api/v2/reports/callcenter/agents/activity/events
Reads CouchDB view _design/fonouc_logs/_view/all_agent_events for the account’s monthly databases in the requested time range.
Query parameters¶
Provide a date range using one of:
| Params | Description |
|---|---|
timeRange |
Relative window, e.g. 1d, 1w, 1M |
startDate + endDate |
Unix timestamps (seconds); maximum 31 days apart; endDate must be greater than startDate |
Pagination:
| Param | Description |
|---|---|
pageSize |
Page size (defaults to the server reports page size if omitted) |
startKey |
Cursor from the previous response next_start_key (Unix timestamp string) |
No server-side user filter
The API returns events for all agents in the account within the time window. Each event includes user_id — filter client-side for a specific user. A userID query parameter is accepted by the shared reports parser but is not applied by this handler.
Example request¶
curl -sS "https://{{ domain }}:9443/api/v2/reports/callcenter/agents/activity/events?startDate=1784515200&endDate=1784601600&pageSize=100" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Account-ID: YOUR_ACCOUNT_ID"
Example: filter to one user (client-side)¶
USER_ID="a2ca7416253d92c8d849ea96f9e2ebe6"
curl -sS "https://{{ domain }}:9443/api/v2/reports/callcenter/agents/activity/events?timeRange=1d&pageSize=500" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-Account-ID: YOUR_ACCOUNT_ID" \
| jq --arg uid "$USER_ID" '.events[] | select(.user_id == $uid)'
Response shape¶
{
"events": [
{
"event": "agent_idle",
"enabled": true,
"user_id": "a2ca7416253d92c8d849ea96f9e2ebe6",
"ext": "3349",
"username": "Sebastian+2 Ripari",
"state": "available",
"Timestamp": 1784602047
}
],
"next_start_key": "1784602047"
}
| Field | Type | Description |
|---|---|---|
events |
array | Page of agent state events (oldest → newest within the page) |
events[].event |
string | State event name (see Event types) |
events[].enabled |
boolean | true = entered this state; false = left this state |
events[].user_id |
string | Agent user ID |
events[].ext |
string | Agent extension |
events[].username |
string | Display name (first_name + last_name from the log) |
events[].state |
string | Extra state detail (custom unavailable label, wrap-up queue name, etc.) |
events[].Timestamp |
number | Event time as Unix seconds (from the CouchDB view key). JSON field name is capital Timestamp. |
next_start_key |
string | Pass as startKey on the next request; empty when there is no further page |
Normalization applied by the API¶
If event is agent_idle and state is empty or "none", the API rewrites state to "available" before returning the event. Stored CouchDB documents may still show "state": "none".
Event types¶
These values are written by the queues app into fonouc_log documents with type: "agent", then exposed through this API.
event |
Meaning when enabled: true |
Typical state |
|---|---|---|
agent_idle |
Agent is available / idle (ready for queue work) | "available" in API responses ("none" in raw DB logs) |
agent_on_call |
Agent is on an active call | usually "none" |
agent_hold |
Agent has a call on hold | usually "none" |
agent_wrap_up |
Agent is in wrap-up / ACW | may be a queue name when wrap-up is anchored to a queue |
agent_dnd |
Agent Do Not Disturb is on | usually "none" |
agent_reg |
Agent device/registration considered registered | usually "none" |
agent_not_avail_state |
Agent selected a “not available” / custom CC status | custom status label or id string |
When enabled is false, the agent left that state (for example wrap-up ended, DND cleared, call hung up).
How to interpret a timeline¶
Events are edge transitions, not a single “current status” field. To reconstruct status over time for one user_id:
- Sort that user’s events by
Timestamp. - Treat each
enabled: trueas entering the named state, andenabled: falseas leaving it. - Several flags can overlap in the underlying system (for example registration vs idle); product reports often treat
agent_idle+enabled: trueas available for queue routing.
What is stored in the database (raw log)¶
For debugging or when reading CouchDB directly, each change is a document like:
{
"account_id": "5d5764bac102d5ad3b6e95ed19920295",
"pvt_type": "fonouc_log",
"timestamp": 1784602047.62461,
"type": "agent",
"user_id": "a2ca7416253d92c8d849ea96f9e2ebe6",
"event": "agent_idle",
"ext": "3349",
"first_name": "Sebastian+2",
"last_name": "Ripari",
"email": "sebastian2@fonouc.com",
"customer_callerid_name": "",
"customer_callerid_number": "",
"state": "none",
"enabled": true,
"_id": "3c75c19de32d0490b91cd40b800e761a",
"_rev": "1-98acda265fdb7b7b31e0dce756537731"
}
| Raw field | API field |
|---|---|
event |
event |
enabled |
enabled |
user_id |
user_id |
ext |
ext |
first_name + last_name |
username |
state |
state (with idle/none → available rewrite) |
timestamp (float) |
Timestamp (integer seconds from the view key) |
The activity API does not return email, caller-id fields, _id, or _rev.
Pagination¶
- Call with
startDate/endDate(ortimeRange) andpageSize. - If
next_start_keyis non-empty, call again withstartKey=<next_start_key>and the same date range. - Repeat until
next_start_keyis empty.
The server skips the duplicate boundary event when startKey is a numeric timestamp.
Related APIs (different purpose)¶
| Endpoint | Purpose |
|---|---|
GET /api/v2/reports/callcenter/agents/activity/events |
Raw agent state-change log (this guide) |
GET /api/v2/reports/callcenter/agents/stats |
Aggregated Agents Activity report |
GET /api/v2/reports/callcenter/queues/agents/status/activity |
Login/logout session activity by queue |
UCP GET /ucp/v2/callcenter/agent/state |
Current custom CC status for the logged-in agent |
| Contact Center Websocket events | Live stream of CC events |
See also¶
- API Key authentication
- Contact Center Websocket events
- Download Call Recordings — same reports-style auth and date-range patterns