Mapping JobCannon Scores to Lever Feedback Forms
Guide to parsing JobCannon results and writing them to Lever Feedback Forms. Covers the Feedback Forms API and dimension mapping.
Mapping JobCannon Scores to Lever Feedback Forms
When a candidate completes a JobCannon assessment, the result is written to a Lever feedback form. This guide explains the result structure and how to map dimensions to feedback fields.
Webhook Payload Structure
When assessment completion is detected, JobCannon sends a webhook to Lever's Feedback Forms API:
{
"opportunityId": "opp_abc123",
"applicationId": "app_xyz789",
"feedbackForm": {
"creator": "jobcannon_bot",
"headline": "JobCannon Assessment: Big Five",
"body": "Assessment completed with overall score of 72 (65th percentile).",
"fields": {
"overall_score": 72,
"overall_percentile": 65,
"assessment_name": "Big Five",
"completed_at": "2026-05-17T14:32:00Z",
"openness_score": 68,
"openness_percentile": 65,
"conscientiousness_score": 81,
"conscientiousness_percentile": 78,
"extraversion_score": 44,
"extraversion_percentile": 32,
"agreeableness_score": 73,
"agreeableness_percentile": 70,
"emotional_stability_score": 55,
"emotional_stability_percentile": 48,
"faking_risk": 32,
"faking_flag": false
},
"profileUrl": "https://app.jobcannon.io/results/[session-id]"
}
}
Field Mapping
Lever feedback forms are semi-structured JSON. JobCannon populates the following standard fields:
| Field | Type | Purpose ||-------|------|---------|| overall_score | number (0–100) | Aggregate assessment score || overall_percentile | number (0–100) | Percentile rank for candidate || assessment_name | string | Name of assessment (e.g., "Big Five") || completed_at | ISO 8601 | Timestamp when candidate submitted || [dimension]_score | number | Raw score per dimension || [dimension]_percentile | number | Percentile per dimension || faking_risk | number (0–100) | Social desirability score || faking_flag | boolean | True if faking detected (>70 risk) |Parsing Results in Lever
To read a JobCannon feedback form from Lever API:
async function getLeverFeedback(opportunityId: string, apiKey: string) {
const response = await fetch(
`https://api.lever.co/v1/opportunities/${opportunityId}/feedback`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
)
const feedback = await response.json()
// Find JobCannon feedback form
const jobCannonFeedback = feedback.data.find((f: any) =>
f.headline?.includes('JobCannon')
)
return {
overallScore: jobCannonFeedback.fields.overall_score,
percentile: jobCannonFeedback.fields.overall_percentile,
dimensions: {
openness: {
score: jobCannonFeedback.fields.openness_score,
percentile: jobCannonFeedback.fields.openness_percentile
},
conscientiousness: {
score: jobCannonFeedback.fields.conscientiousness_score,
percentile: jobCannonFeedback.fields.conscientiousness_percentile
}
// ... other dimensions
},
fakingRisk: jobCannonFeedback.fields.faking_risk
}
}
Feedback Form Lifecycle
1. **Assessment sent:** Candidate receives email with assessment link
2. **Candidate completes:** Assessment is scored in <1 second
3. **Webhook triggered:** JobCannon sends feedback to Lever API
4. **Feedback created:** Form appears on opportunity record in Lever
5. **Recruiter reviews:** Hiring team can see score + narrative
If the PATCH to Lever fails, JobCannon retries with exponential backoff (5s → 15s → 60s) for up to 24 hours.
Handling Abandoned Assessments
If a candidate closes the browser before submitting:
EEOC Compliance
Use percentile ranks (not raw scores) when analyzing fairness:
// Calculate selection rate by group
const whitePassRate = passCount / whiteTotal
const blackPassRate = passCount / blackTotal
const ratio = blackPassRate / whitePassRate
// 4/5ths rule: if ratio < 0.8, investigate bias
if (ratio < 0.8) {
console.warn('Potential adverse impact detected')
}
Rate Limits
Lever feedback API: 10 requests/second. If throttled (429), wait before retrying.
---
**Vendor docs:** https://hire.lever.co/integrations
**Feedback API:** https://api.lever.co/v1/docs#feedback-forms
**Support:** [email protected]