Invitations

Invitations

Invite candidates, and resend, extend or cancel their links.

An invitation sends one candidate one interview. Reading needs candidates:read; everything that changes an invitation needs invitations:send.

The invitation object

FieldType
idstringinv_…
object"invitation"
statusstringpending, started, completed, abandoned, expired or canceled. See Concepts.
interviewer_idstring
candidate_idstring
session_idstring
urlstring or nullThe candidate's link. null once the invitation is no longer pending.
expires_attimestamp or nullWhen the link stops working
external_refstring or nullYour reference, echoed back
tagsstring[]
metadataobject
attempt_numberintegerGoes up when a candidate is given another attempt
resend_countinteger
first_sent_at, last_sent_attimestamp or nullWhen the first and latest links were issued
livemodeboolean
created_attimestamp

List invitations

GET /invitations. Filters: interviewer_id, candidate_id, status, external_ref, created_gte, created_lt.

Create an invitation

POST /invitations

Field
interviewer_idrequiredint_…
candidaterequired{ email, name, phone?, external_id? }. Creates the candidate or updates the existing one with that email.
external_refoptionalUp to 200 characters. Filter sessions and invitations by it later.
tagsoptionalUp to 20 strings
metadataoptionalObject
send_emailoptionalDefault true. Set false to deliver the url yourself.
expires_atoptionalISO 8601 time the link stops working. Must be in the future and at most 90 days out. Default 14 days.

Returns the invitation with status 201. Send an idempotency key so a retry cannot invite twice.

In live mode, a request fails with 403 credits_exhausted when the organisation has no credits left.

Bulk invite

POST /invitations/bulk invites up to 500 candidates to one interviewer and returns 202 straight away. Links are created and sent in the background; each one fires an invitation.created event.

{
  "interviewer_id": "int_…",
  "candidates": [
    { "email": "ada@example.com", "name": "Ada Lovelace", "external_ref": "app-1" },
    { "email": "alan@example.com", "name": "Alan Turing", "external_ref": "app-2" }
  ],
  "send_email": true,
  "expires_at": "2026-10-20T00:00:00Z"
}
{ "object": "bulk_invitation", "queued": 2, "skipped": [] }

skipped lists rows rejected up front, such as emails that belong to the other mode. For spreadsheets, use an import instead.

Retrieve an invitation

GET /invitations/{id}

Resend an invitation

POST /invitations/{id}/resend issues a fresh link and, unless send_email is false, emails it. The old link stops working.

Extend an invitation

POST /invitations/{id}/extend with { "days": 7 } (1 to 90) pushes the expiry out from whichever is later: now or the current expiry. Works on pending and expired invitations; others return 400 invalid_request.

Cancel an invitation

POST /invitations/{id}/cancel closes a pending invitation. The link stops working at once, the invitation becomes canceled and its session cancelled. An invitation that has started cannot be cancelled.