Embedding and links
Getting the candidate into the assessment.
Two ways in. Pick one.
A link you send
curl -X POST https://api.experthire.cloud/v1/assessments/$ASSESSMENT_ID/launch-link \
-H "Authorization: Bearer $EH_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"expires_in_seconds": 604800}'
Still a placeholder: $ASSESSMENT_ID, $EH_SECRET_KEY. Add them under Your values above.
{
"object": "launch_link",
"url": "https://careers.example.com/launch/ehs_lt_9Qm2...",
"assessment_id": "3b8e1d02-5c77-4c2a-8a41-9b2f7e6d4c10",
"expires_at": 1767830400,
"livemode": true
}
Single use, seven days by default and seven at most. The URL resolves to the customer's own branded domain when one is configured, so the candidate never sees ours.
The token is hashed at rest, so a database read cannot mint a session from it. Opening it
twice returns launch_token_used.
Embedded in your page
Three steps, and the secret key stays on your server throughout.
1. Allowlist your origin, once.
curl -X POST https://api.experthire.cloud/v1/domains \
-H "Authorization: Bearer $EH_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"origin": "https://app.example.com"}'
Still a placeholder: $EH_SECRET_KEY. Add it under Your values above.
Exact match on scheme, host and port. No wildcards.
This is not CORS. Adding an origin here gates session minting and framing; it will
never add an Access-Control-Allow-Origin header to any response.
2. Mint a session on your server, scoped to one assessment, and hand the token to the page.
curl -X POST https://api.experthire.cloud/v1/sessions \
-H "Authorization: Bearer $EH_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"assessment_id": "$ASSESSMENT_ID", "origin": "https://app.example.com"}'
Still a placeholder: $EH_SECRET_KEY, $ASSESSMENT_ID. Add them under Your values above.
{
"object": "session",
"session_token": "eyJhbGciOiJFZERTQSIsImtpZCI6...",
"jti": "c4a1f9e2-8b73-4d16-9f05-2e7c3a8d6b41",
"expires_at": 1767226500,
"refresh_after": 1767226320,
"assessment_id": "3b8e1d02-5c77-4c2a-8a41-9b2f7e6d4c10",
"environment": "live",
"livemode": true
}
3. Run the room. The page uses the session token, never the secret key. These four are the whole runtime.
| Call | Purpose |
|---|---|
GET /v1/session | What to render, including the capability flags below |
POST /v1/assessments/{id}/join | Realtime credentials; starts the interview |
GET /v1/assessments/{id}/timer | Server-authoritative remaining time |
POST /v1/assessments/{id}/end | Close the room |
join is idempotent. Rejoining after a refresh or a dropped connection returns fresh
realtime credentials without restarting the clock or dispatching a second interviewer.
4. Refresh before it expires. The response carries refresh_after; call
POST /v1/sessions/refresh with the session token before that. A mid-interview 401 is the
most common embedding bug.
Code editor and whiteboard
GET /v1/session and the join grant both return supports_code_editor and
supports_whiteboard. Render the matching surface when they are true and post the work
back as the candidate goes:
| Call | Purpose |
|---|---|
POST /v1/assessments/{id}/code | Save the editor contents |
POST /v1/assessments/{id}/whiteboard | Save the whiteboard |
These flags come from the round type, not from the assessment. A coding round sets
supports_code_editor and a system_design round sets supports_whiteboard; the
default general_interview sets neither. If you create an assessment without passing
round_type, you get general_interview and no editor. This is the most common reason
the editor appears to be missing, and it is not related to sandbox.
Save as you go rather than only at the end. The interviewer scores whatever was last posted, so unsaved work at the final moment is not scored.
Origin is checked every request
The session token travels in a URL fragment, so binding the origin once at mint would let a stolen token replay from anywhere. It is re-checked on every call.
Revoking
DELETE /v1/sessions/{jti} ends a session immediately. The row behind the token is what
makes that real; the JWT alone would stay valid until it expired.