Connecting JobCannon to Lever
JobCannon has no native Lever adapter yet. What works today: the hosted invite API, with the invitation created by your integration and the result posted back to you.
JobCannon has no native Lever adapter today. This page used to describe an OAuth app, a webhook registration and a scorecard field mapping for Lever, none of which shipped. Rather than leave that standing, here is what is actually available and how to use it.
What ships today
| Path | Status |
|---|---|
| Greenhouse Assessment Partner API | Live |
| Ashby partner assessments | Built, enabled per organisation on request |
| Assessment API (X-API-Key) | Live |
A Lever adapter is on the roadmap with no committed date. If you want one, email partners@jobcannon.io with your candidate volume — that is what decides the order they get built in, and a named customer moves an ATS up the list faster than anything else does.
What works with Lever right now
The hosted invite API. Your integration — or an automation tool sitting beside Lever — creates the invitation, JobCannon emails the candidate and hosts the assessment, and JobCannon calls you back when it is done. You write the result into Lever using Lever's own API.
This is not a downgrade in the result you get: it is the same standardised envelope a native adapter delivers, over a transport you control.
1. Get a key
Email partners@jobcannon.io with your organisation name and the address to send credentials to. Keys carry scopes: sending needs assessments:send, reading results needs assessments:read.
2. Send an invitation
curl -X POST https://jobcannon.io/api/v1/invites \
-H "X-API-Key: $JOBCANNON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"test_slug": "big-five",
"candidate_email": "candidate@example.com",
"candidate_first_name": "Alex",
"candidate_last_name": "Morgan",
"external_id": "<your Lever record id>",
"callback_url": "https://your-app.example.com/hooks/jobcannon",
"sandbox": true
}'Answers 201 with session_id, assessment_url, test, test_name, status, locale, candidate_email, sandbox and email_delivered.
- **
external_id** is echoed back untouched on the callback — put your Lever record id there and you will not need a lookup table. - **
callback_url** must be absolutehttpsand a public host. Loopback and private ranges are rejected, so you cannot point the flusher at internal infrastructure. - **
sandbox: true** runs the whole cycle without emailing anyone.email_deliveredcomes backnullrather than true/false, because no mail was attempted. Take it out when you go live. Leave it in while you are testing: the live path emails a real person. - **
assessment_url** is the candidate's link. If you would rather deliver it yourself — in your own email, or pasted into Lever by a recruiter — take it from here. - **
locale** is echoed back even if you did not send it, because your organisation may have a default. It tells you which language the candidate was written to, and which languagetest_nameis in.
3. Receive the result
JobCannon POSTs to your callback_url when the candidate finishes, with header X-JobCannon-Event: assessment.completed. The payload and every field in it are documented on the score mapping page.
The callback is an unsigned notification. If you need an authenticated confirmation of it, re-read the invite — that response is scoped to your own key:
curl -H "X-API-Key: $JOBCANNON_API_KEY" \
https://jobcannon.io/api/v1/invites/{session_id}Polling works on its own too: omit callback_url entirely and read this endpoint. Poll no more than once a minute — assessments take minutes to hours of wall-clock time.
Writing it into Lever
Lever exposes opportunity notes and stage transitions over its own API. The usual pattern is to post primary_outcome.label plus the result permalink as a note on the opportunity — a link a hiring manager can open beats a number they cannot interpret. Lever's API reference is linked below; JobCannon does not call it on your behalf.
Common errors
**401 missing_api_key** — no X-API-Key header reached us.
**401 invalid_api_key / 401 revoked_api_key** — the key is not recognised, or it was revoked. Both are deliberate: a revoked key says so rather than pretending it never existed.
**403 insufficient_scope** — the key is valid but was issued without the scope this endpoint needs. The message names the missing scope. Email partners@jobcannon.io to widen it.
**400 test_not_sendable** — the slug is not in the hire-eligible catalogue. Slugs are dashed (big-five, not big_five). **The error response lists every allowed slug in its allowed array** — send a deliberately bad one once and you have the catalogue.
**429 rate_limited** — per-key, not per-IP. resetAt in the body tells you when to retry.
Callback never arrives — check your endpoint answers 2xx and is reachable from the public internet. A failed callback retries with backoff (10 min → 30 min → 2 h → 6 h, five attempts) then stops. The result is never lost: read it with GET /api/v1/invites/{session_id} at any point afterwards.
Lever docs: https://hire.lever.co/developer/documentation Support: partners@jobcannon.io