CXone GET /agents/states returning empty array - agent not showing as logged in

GET /api/v2/users/me returns the user details but the presence field is null or missing, even though the agent is logged into the desktop client. The dashboard backend keeps flagging them as offline.

  • C# HttpClient with Bearer token from client credentials grant
  • Verified token scopes via jwt.io
  • Checked agent ID against the response from /api/v2/users/me
  • Retried request with different timezone headers
    Response code is 200, but the presence data stays blank. The .NET SDK wrapper throws the same result. Token expiration isn’t an issue since other endpoints work fine. Don’t see any auth errors in the trace. What parameter forces the presence state to populate? Still tracing the request.

The routing state API doesn’t directly reflect desktop login status. It only returns records when the user enters an active routing state via a state change event (e.g., available, ready). If the dashboard shows offline while the desktop is open, the routing session likely timed out or the agent transitioned to a non-routing state like break. Double-check your bearer token scopes first. Client credentials require agent:view and user:read. Without agent:view, it will silently return []. Also, verify the divisionId in your request aligns with the agent’s assigned division; the API filters by division context automatically. A mismatched division will result in an empty array.

For your C# HttpClient, explicitly add the Accept: application/json header. Some proxies strip the response body without it. Since there is no direct endpoint to query an agent’s current routing state by user ID, you must rely on the state change event stream or check the user’s presence via the user details endpoint. The base path aggregates all divisions and can quickly hit rate limits. When integrating with a DCA, ensure the response is correctly parsed. The agentState object contains stateId and stateName. If stateId is offline, the routing engine considers the agent inactive.

To force a routing engine sync, you can send a notification that an agent’s state changed using the outbound campaign agent endpoint, though this is typically used for outbound campaigns. Alternatively, investigate the agent’s session history in Control Manager to confirm recent state transitions.

Routing state checks out, but I ran into this “ghost login” issue migrating from another platform. Here’s how I debugged it. First, swapped the client credentials grant for a standard user token to rule out missing agent:view scopes. That failed with a 403. Second, bypassed the C# HttpClient and hit the endpoint with raw curl. Still got an empty array. Third, verified the actual routing state payload instead of trusting the desktop UI.

curl -X GET "https://api.cxone.net/api/v2/agents/states?userId={agentId}" \
 -H "Authorization: Bearer {your_token}" \
 -H "Accept: application/json"

It’s almost always an idle timeout killing the routing session after thirty minutes. Check the agent’s recent activity in Interaction History to confirm they’ve actually touched a queue. I don’t think it’s a scope issue. Does your environment have the idle timeout set to auto-logout, or are you forcing state changes through a custom webhook? Our setup just drops the WebSocket connection and leaves the dashboard hanging. Look into the agent status updates in Control Manager.

2 Likes