Mapping JobCannon Scores to Workable Fields
Technical reference for parsing JobCannon assessment results in Workable and mapping dimensions to scorecard fields.
Mapping JobCannon Scores to Workable Fields
When a candidate completes a JobCannon assessment in Workable, the result is returned via the Assessment API. This guide explains how to parse and display the results.
Result Structure via Assessment API
When JobCannon completes an assessment, the result is available through Workable's Assessment API endpoint:
GET https://www.workable.com/spi/v3/accounts/{subdomain}/candidates/{candidate_id}/assessments/{assessment_id}
Response:
{
"id": "assess_abc123",
"candidate_id": "cand_xyz789",
"assessment_type": "jobcannon",
"status": "completed",
"completion_date": "2026-05-17T14:32:00Z",
"result": {
"overall_score": 72,
"overall_percentile": 65,
"assessment_name": "Big Five",
"completed_at": "2026-05-17T14:32:00Z",
"duration_seconds": 245,
"dimensions": [
{
"name": "Openness",
"score": 68,
"percentile": 65,
"interpretation": "above_average"
},
{
"name": "Conscientiousness",
"score": 81,
"percentile": 78,
"interpretation": "high"
}
],
"metadata": {
"faking_detected": false,
"social_desirability_scale": 32
},
"profile_url": "https://app.jobcannon.io/results/[session-id]"
}
}
Parsing the Assessment Result
Here's a TypeScript example to extract assessment data from the Workable API:
interface WorkableAssessmentResult {
id: string
candidate_id: string
status: string
result: {
overall_score: number
overall_percentile: number
assessment_name: string
dimensions: Array<{ name: string; score: number; percentile: number }>
metadata: { faking_detected: boolean; social_desirability_scale: number }
}
}
async function parseWorkableAssessment(candidateId: string, assessmentId: string) {
const response = await fetch(
`https://www.workable.com/spi/v3/accounts/my_account/candidates/${candidateId}/assessments/${assessmentId}`,
{ headers: { Authorization: `Bearer ${accessToken}` } }
)
const assessment: WorkableAssessmentResult = await response.json()
// Extract dimensions into key-value pairs
const dimensionMap = assessment.result.dimensions.reduce((acc, dim) => {
acc[dim.name.toLowerCase().replace(/\s+/g, '_')] = {
score: dim.score,
percentile: dim.percentile
}
return acc
}, {} as Record<string, any>)
return {
overallScore: assessment.result.overall_score,
percentile: assessment.result.overall_percentile,
dimensions: dimensionMap,
fakingRisk: assessment.result.metadata.social_desirability_scale,
profileUrl: assessment.result.profile_url
}
}
Mapping to Workable Evaluation Form
Workable evaluation forms accept structured data. Map JobCannon dimensions as follows:
| JobCannon | Workable Field | Type ||---|---|---|| overall_score | Assessment Score | Number (0–100) || overall_percentile | Percentile | Number (0–100) || dimension.score | [Dimension] Score | Number (0–100) || dimension.percentile | [Dimension] Percentile | Number (0–100) || social_desirability_scale | Faking Risk | Number (0–100) || faking_detected | Needs Review | Boolean flag |Assessment Lifecycle in Workable
1. **Candidate receives email:** Link to JobCannon assessment
2. **Candidate completes:** Assessment is scored in <1 second
3. **Result stored:** Available via Assessment API
4. **Evaluation form created:** Linked to the candidate record
5. **Recruiter reviews:** Can view score + interpretation in Workable UI
To retrieve all assessments for a candidate:
GET https://www.workable.com/spi/v3/accounts/my_account/candidates/{candidate_id}/assessments
Response:
[
{
"id": "assess_abc123",
"assessment_type": "jobcannon",
"status": "completed",
"result": { ... }
}
]
Handling Faking Flags
If social_desirability_scale > 70, mark the assessment for review:
if (assessment.result.metadata.social_desirability_scale > 70) {
await addEvaluationNote(candidateId, {
type: 'flag_for_review',
message: 'Assessment flagged for possible response bias. Consider re-testing.'
})
}
Webhook Deliverability
JobCannon sends assessment completion events via webhook to Workable. If delivery fails, Workable retries with exponential backoff (5s → 15s → 60s) for up to 24 hours. Your webhook endpoint must return HTTP 200 to confirm receipt.
Idempotency
Include an `X-Idempotency-Key` header on assessment updates to prevent duplicate processing:
const idempotencyKey = `assessment_${assessmentId}_${timestamp}`
const response = await fetch(assessmentUrl, {
method: 'PATCH',
headers: {
'X-Idempotency-Key': idempotencyKey,
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(updatePayload)
})
EEOC Adverse Impact Monitoring
Use percentile ranks for fairness analysis:
const whitePassRate = passCount / whiteCandidates
const blackPassRate = passCount / blackCandidates
if ((blackPassRate / whitePassRate) < 0.8) {
console.warn('Potential adverse impact')
}
---
**Vendor docs:** https://developers.workable.com/reference/assessment-api
**Evaluation forms:** https://developers.workable.com/reference/evaluation-forms
**Support:** [email protected]