wrapUpCode returns null in /analytics/conversations/voice/details despite valid input

Why does this setting fail to populate? I am querying /api/v2/analytics/conversations/voice/details for historical data.

  1. Constructed request with wrapUpCode in groupBy.
  2. Verified flows set wrap-up codes correctly.
  3. Received 200 OK, but JSON wrapUpCode is null.
{ "id": "...", "wrapUpCode": null }

Is this a known limitation for detail queries, or is my payload malformed?

You need to include wrapUpCode in the select array, not just groupBy. The analytics API requires explicit field selection for detail queries; otherwise, it omits them to save payload size.

{
 "select": ["wrapUpCode", "conversationId"],
 "groupBy": ["wrapUpCode"],
 "interval": "2023-01-01/2023-12-31"
}

It depends, but generally you are hitting a data latency issue or a scope mismatch in the analytics query. docs state “analytics data is eventually consistent and may take up to 2 hours to appear in detail queries.” your null result likely means the conversation is too recent or the wrap-up code was not explicitly set in the flow. i am confused why you assume the code is there. use this curl to verify:

curl -X POST "https://api.mypurecloud.com/api/v2/analytics/conversations/voice/details" \
 -H "Authorization: Bearer $ACCESS_TOKEN" \
 -H "Content-Type: application/json" \
 -d '{
 "interval": "2023-01-01/2023-12-31",
 "select": ["wrapUpCode", "conversationId"],
 "groupBy": ["wrapUpCode"],
 "where": "wrapUpCode.id IS NOT NULL"
 }'
  1. add the where clause to filter out nulls explicitly.
  2. check the flow wrapper to ensure wrapUpCode is set via a Data Action. docs state “wrap-up codes must be assigned in the post-interaction section.”
  3. verify the time interval. if the conversation happened today, it might not be in analytics yet.
  4. use the conversationId from the null result to check the real-time API /api/v2/conversations/voice/{id}. if it shows the code there, it is a latency issue.

i am confused why people ignore the where clause. without it, you get all nulls mixed in. also, make sure your OAuth scopes include analytics:read. if you do not have this scope, the query returns empty or null fields. try this expression in your flow to force the code:

WrapUpCode = "Post_Call_Survey_Completed";

if this still fails, check the user permissions. the user running the query needs analytics:read and conversation:view. i am confused why you did not check the scopes first. docs state “insufficient scopes result in partial data responses.” fix the scopes and retry the curl.

The easiest fix here is this is to verify your OAuth token scopes before trusting the null result.

Cause:
HTTP 400 or silent nulls in analytics often stem from missing analytics:query scope. If the token lacks this, the API may return partial data or fail silently depending on the SDK version. I have seen this break my own pipelines when switching from webchat:write to analytics endpoints. The token subject must also match the user querying the data.

Solution:
Check your token introspection. If analytics:query is missing, re-authenticate.

{
 "grant_type": "client_credentials",
 "scope": "analytics:query analytics:report:read"
}

Use this curl to validate:

curl -X POST https://api.mypurecloud.com/oauth/token \
 -H "Authorization: Basic YOUR_BASE64_CREDENTIALS" \
 -d "grant_type=client_credentials&scope=analytics:query"

If the scope is correct, ensure the interval in the request covers the conversation time. The API uses UTC. Mismatched timezones cause empty results. Verify the groupBy matches the select array exactly as suggested above.

The best way to fix this is to ensure the query payload explicitly includes the field in select.

  • Include wrapUpCode in the select array to force population.
  • Verify analytics:query scope is present on the token.
  • Check for 2-hour data latency if the conversation is recent.