GET /api/v2/agents/states returns an empty array 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
Retried request with different timezone headers
Response code is 200, but the payload 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 state array to populate? Still tracing the request.
The GET /api/v2/agents/states endpoint doesn’t track desktop connection status. It only returns records when the user enters an active routing state via agent:login or agent:available. If the dashboard shows offline while the desktop stays open, the routing session likely expired or the user clicked agent:break. Check the bearer token scopes first. The client credentials grant requires agent:view plus user:read. Without agent:view, it’ll silently return []. Also verify the divisionId matches the agent record. The API filters by division context automatically. If passing a wrong division token, the array stays empty. Messy behavior. Check the logs. Usually a scope mismatch.
For the C# HttpClient, add the Accept: application/json header explicitly. Some proxy servers drop the response body without it. Use await client.GetAsync($"api/v2/agents/states/{userId}") instead of the base path. The base path aggregates all divisions and often hits rate limits. When wiring this into an Architect data action, wrap the response in {{response.body}} and check {{response.statusCode}} before parsing. The agentState object contains state.id and state.name. If state.id equals offline, the routing engine considers them inactive. Run a quick POST /api/v2/agents/{userId}/states with {"stateId": "available"} to force the routing engine sync. The routing engine only updates on explicit state changes.
The routing state explanation checks out, but I hit this same ghost login issue migrating Five9 logic. Here’s the debug path. First, I swapped the client credentials grant for a standard user token to rule out missing agent:view scopes. That failed with a 403. Second, I bypassed the C# HttpClient entirely and hit the endpoint with raw curl. Still got an empty array. Third, I verified the actual routing state payload instead of trusting the desktop UI.
It’s almost always an idle timeout killing the routing session after thirty minutes. You’ll want to check the conversation history endpoint to see if the agent actually touched a queue recently. 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.