Quick question, has anyone seen this weird error? with Quality Evaluation data in our bulk export jobs. The evaluation_score field returns null for WhatsApp interactions in v2024.09, even though the audit trail shows the score was finalized. Is this a known limitation for digital channel metadata?
It depends, but generally the bulk export endpoint /api/v2/quality/evaluations/export doesn’t fully hydrate the score object for digital channels if the evaluation was closed via the API rather than the UI. The JSON payload often strips the computed evaluation_score when status is CLOSED but the completedBy field points to a system user or a bot integration.
i’ve run into this exact issue with WhatsApp transcripts in my Playwright E2E suites. when spinning up test data via genesyscloud.platformClient, the quality:evaluation:write scope lets you create the eval, but the bulk export job runs asynchronously and sometimes misses the final score calculation if the metadata object isn’t explicitly populated with channelType: "whatsapp".
you need to verify the evaluation state directly via the GET /api/v2/quality/evaluations/{evaluationId} endpoint first. check the score property in the response body. if it’s null there, the export will definitely be null.
here’s a quick snippet from my test utils to force the score update before triggering the export:
const updateEval = async (client: PureCloudPlatformClientV2, evalId: string, score: number) => {
const body = {
score: score,
status: "CLOSED",
comments: [{ text: "Automated score update", section: "General" }]
};
// Use the internal API path for direct manipulation if UI sync is lagging
await client.QualityApi.postQualityEvaluation({
evaluationId: evalId,
body: body
});
};
also, make sure your export job configuration includes includeMetadata: true. without that flag, digital channel specific fields like whatsappMessageId or score get truncated. it’s a known quirk in the v2024.09 release where the batch processor skips score aggregation for non-voice channels unless explicitly requested.
check the evaluationResponse object in the export JSON. if you see metadata but no score, it’s likely a timing issue with the async job. retry the export after a 30-second delay or trigger a manual re-evaluation via the API to force the score to persist.
you might want to look at the raw audio export endpoint instead. the quality api seems flaky for digital channels anyway. we’re pulling the recording directly via GET /api/v2/recordings/{recordingId}/metadata and sending the mp3 to our biometrics vendor for scoring. bypasses the whole json null issue. just works better for voice analytics.
The problem here is that the bulk export API often drops derived fields like evaluation_score for digital channels when the evaluation metadata isn’t fully hydrated in the initial query response.
// Don't rely on the export JSON for the final score.
// Fetch it directly via the Quality API instead.
String evalId = "your-evaluation-id";
Evaluation evaluation = qualityApi.getEvaluation(evalId, null, null).get();
if (evaluation.getScore() != null) {
System.out.println("Final Score: " + evaluation.getScore().getTotal());
} else {
// Handle missing score gracefully
log.warn("Score null for digital channel: " + evalId);
}
just pull the specific evaluation by ID after the export finishes. the export job is optimized for volume, not depth, so it skips the nested score object to save bandwidth. if you’re processing thousands of records, batch these GET requests to avoid hitting the 100 req/min limit per org. also check if the completedBy user is an API key, which sometimes triggers the null behavior mentioned earlier.
This looks like a hydration issue with the export job rather than a missing score. the bulk export endpoint often skips computed fields for digital channels if the evaluation status changed while the job was running.
- check the evaluation status in the raw response. if it’s
CLOSEDbutcompletedByis a system user, the score field gets stripped. - verify the OAuth scope. the export job needs
quality:evaluation:readplusanalytics:report:readto pull the final computed score. - switch to the direct GET endpoint for validation. don’t rely on the bulk export JSON for the final score. fetch it directly via the Quality API instead.
// .NET SDK example
var qualityApi = new QualityApi();
var evalId = "your-eval-id";
var response = await qualityApi.GetQualityEvaluationAsync(
evalId,
expand: new[] { "score", "metadata" }
);
if (response.EvaluationScore != null)
{
Console.WriteLine($"Score: {response.EvaluationScore}");
}
the export job runs asynchronously. if the evaluation closes while the job is processing, the snapshot might miss the final score calculation. the direct API call forces a fresh read.
also, make sure you’re not hitting the rate limit. the .NET SDK doesn’t handle backoff automatically for bulk calls. add a simple retry loop with exponential backoff.
// simple retry logic
int retries = 3;
while (retries > 0)
{
try
{
var result = await qualityApi.GetQualityEvaluationAsync(evalId);
break;
}
catch (Exception ex) when (ex.Status == 429)
{
Thread.Sleep((int)Math.Pow(2, 3 - retries) * 1000);
retries--;
}
}
this usually fixes the null score issue. if it’s still null, check the audit trail. the score might be pending recalculation.