Invite candidates to a one-way video interview from your own systems, and get AI-scored results back the moment they are ready. Every endpoint, payload and event is documented on this page.
No sales call, no access request. Create a key in your account settings and start in about a minute.
Base URL
https://voxscreen.com/api/integrations/v1
This is a published contract. Fields get added, never removed or renamed. A breaking change would arrive as a new version at /api/integrations/v2.
Quickstart
Four steps from nothing to a scored candidate arriving at your own endpoint.
1
Create an API key
In VoxScreen, open Settings and then Integrations. The key is shown once, so copy it before you close the dialog. Every plan has API access, the free one included.
2
Check that it works
If this returns your account name, you are connected.
Subscribe to submission.scored and we POST to your endpoint as soon as the answers are transcribed and scored. Keep the secret from the response: you need it to verify deliveries.
Every request needs an API key, sent in either header. Keys start with vs_live_ followed by 43 random characters.
curl
curlhttps://voxscreen.com/api/integrations/v1/me\-H"Authorization: Bearer vs_live_YOUR_KEY"# X-API-Key works too, if that suits your client bettercurlhttps://voxscreen.com/api/integrations/v1/me\-H"X-API-Key: vs_live_YOUR_KEY"
A key belongs to an account, not to a person, so removing an employee's login does not break the automations they set up.
API access is included on every plan. A 402 means the subscription has lapsed, not that the plan is too small.
Endpoints
All paths are relative to the base URL above. Responses are JSON.
GET/me
Identify the account
Returns the account behind the key. Useful as a connection test, which is exactly what Zapier and Make use it for.
Newest first. Most integrations use this to populate a dropdown so a user can pick which interview candidates should be invited to.
Query parameters
status
string
draft, active, closed or archived.
limit
integer
1 to 200, default 100.
Response
JSON
[{"id":"9c1a0f10-0000-4000-8000-000000000001","title":"Backend Tech Lead","description":"Screening for a backend tech lead role.","status":"active","language":"en","time_limit_seconds":1800,"expires_at":"2026-09-01T23:59:00Z","created_at":"2026-08-01T12:00:00Z"}]
POST/candidates/invite
Invite a candidate
Creates the candidate if the email is new to your account and reuses the existing record otherwise, so re-running the same call does not duplicate anyone. Sends the invitation email and counts against your monthly candidate quota.
The interview must be active. Returns 400 if it is not, if the email is disposable, or if the quota is exhausted.
Newest finished first, so a poller can stop reading once it recognises an id. Poll with status=scored and since set to your last run to pick up new results.
Every submission carries results_url, a link to the transcript, scores and recording in VoxScreen. Pass it along in a Slack message or an ATS note so whoever reads it can open the result in one click. Preview submissions, which are recruiters testing their own interview, are never included.
Query parameters
status
string
pending, in_progress, completed, scoring, scored or expired.
interview_id
uuid
Restrict to a single interview.
since
ISO 8601
Only submissions completed at or after this time.
limit
integer
1 to 100, default 50.
Response
JSON
[{"id":"d46e6040-0000-4000-8000-000000000001","interview_id":"9c1a0f10-0000-4000-8000-000000000001","candidate_id":"7d900000-0000-4000-8000-000000000001","status":"scored","results_url":"https://voxscreen.com/submissions/d46e6040-0000-4000-8000-000000000001","started_at":"2026-08-07T16:01:15Z","completed_at":"2026-08-07T16:08:40Z","overall_score":4.2,"percentile":78.0,"language_proficiency":"B2","language_proficiency_reasoning":"Fluent, occasional hesitation.","ai_summary":"Strong communication and relevant backend experience.","created_at":"2026-08-07T16:00:02Z","interview_title":"Backend Tech Lead","candidate_name":"Alex Silva","candidate_email":"alex.silva@example.com"}]
GET/submissions/{id}
Get one submission
Same shape as a list entry. Returns 404 for a submission belonging to another account, never 403.
Response
JSON
{"id":"d46e6040-0000-4000-8000-000000000001","status":"scored","results_url":"https://voxscreen.com/submissions/d46e6040-0000-4000-8000-000000000001","overall_score":4.2,"language_proficiency":"B2","ai_summary":"Strong communication and relevant backend experience.","candidate_name":"Alex Silva","candidate_email":"alex.silva@example.com"}
POST/hooks
Subscribe to an event
Registers a URL we POST to when the event fires. The signing secret is in this response and nowhere else.
target_url must be https. Subscribing the same key to the same event and URL twice returns the existing subscription instead of creating a duplicate, so a retried call is safe.
{"event":"submission.scored","created_at":"2026-08-08T02:09:04.713338+00:00","data":{"submission_id":"d46e6040-0000-4000-8000-000000000001","results_url":"https://voxscreen.com/submissions/d46e6040-0000-4000-8000-000000000001","status":"scored","overall_score":4.2,"percentile":78.0,"language_proficiency":"B2","ai_summary":"Strong communication and relevant backend experience.","started_at":"2026-08-07T16:01:15Z","completed_at":"2026-08-07T16:08:40Z","interview":{"id":"9c1a0f10-0000-4000-8000-000000000001","title":"Backend Tech Lead"},"candidate":{"id":"7d900000-0000-4000-8000-000000000001","full_name":"Alex Silva","email":"alex.silva@example.com"}}}
candidate.invited carries invitation_id, status, sent_at, interview and candidate instead.
X-VoxScreen-Delivery is unique per attempt. Use it to make your handler idempotent, since a retry repeats the payload.
Verifying a delivery
Compute HMAC-SHA256 over the raw request body using your subscription secret, and compare it in constant time.
Verify against the bytes you received, not a re-serialised object. Any difference in whitespace or key order changes the signature.
Retries and failures
Any non-2xx response is retried five times with exponential backoff, so a single event is attempted up to six times in all. Respond 2xx quickly and do the work asynchronously: deliveries time out after 10 seconds.
·30s · 60s · 120s · 240s · 480s
·Return 410 Gone to unsubscribe immediately. This is how a consumer signals that an endpoint is retired, and it stops all further deliveries.
·Attempts are counted one by one, retries included, and a subscription switches off after 10 failures in a row. Because each event is attempted six times, that is under two failed events, or roughly 20 minutes of an endpoint being down. Any 2xx resets the count to zero. A disabled subscription stays visible in your settings, so alert on your own endpoint rather than relying on us to keep trying.
Errors and limits
Errors return {"detail": "..."}. Validation errors return an array under detail naming each offending field.
401
Missing, malformed, unknown or revoked key.
402
Valid key, but the subscription has lapsed. Plan does not matter; every plan has API access. The body carries current_plan.
404
The resource does not exist, or belongs to another account. Deliberately indistinguishable, so the API never confirms an id exists.
422
Validation failure. The body lists the offending fields.
429
Rate limit exceeded.
120 requests per minute, per key, per endpoint. Zapier and Make poll well inside this.
Prefer no code?
You do not have to write any of this. Zapier and Make connect VoxScreen to thousands of tools, and you can add a webhook straight from Settings and then Integrations without touching an API key.