Assess API · v1
Invitations
Programmatically invite candidates from your ATS or internal hiring tool. All invite endpoints are idempotent — re-inviting the same email returns the existing invitation rather than creating a duplicate.
https://praxicraft.com/api/v1/public/assessments/:slug/invites/Create Invitation
Creates a unique assessment link for one candidate. Idempotent: if the email was already invited to this assessment, returns the existing invitation with HTTP 200 (not 201).
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| string | required | Candidate email address | |
| name | string | optional | Candidate full name (displayed in the email and on the landing page) |
| role | string | optional | Job role or position the candidate is being screened for (e.g. Senior Backend Engineer). Shown in the invitation email. |
| send_email | boolean | optional | Set true to immediately dispatch the invitation email (default: false) |
Response Fields
| Field | Type | Description |
|---|---|---|
| message | string | Confirmation message |
| invite_token | uuid | Unique token for this invitation — use this to fetch results later |
| invite_url | url | Direct link the candidate opens to start the assessment |
| expires_at | ISO 8601 | Invitation expiry (7 days from creation) |
| status | string | pending | started | completed | expired |
POST /api/v1/public/assessments/senior-backend-screen/invites/
Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
{
"email": "jane.doe@example.com",
"name": "Jane Doe",
"role": "Senior Backend Engineer",
"send_email": true
}Example Response
{
"message": "Invitation created successfully.",
"invite_token": "c7b3e2a1-1234-5678-abcd-ef0123456789",
"invite_url": "https://praxicraft.com/take/c7b3e2a1-1234-5678-abcd-ef0123456789",
"expires_at": "2025-03-22T10:00:00Z",
"status": "pending"
}https://praxicraft.com/api/v1/public/assessments/:slug/invites/bulk/Bulk Create Invitations
Creates invitations for multiple candidates in one request. Emails that were already invited are silently skipped and returned in the `skipped` array. Useful for ATS batch imports.
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| candidates | array | required | Array of candidate objects, each with `email` and optional `name` and `role` |
| send_email | boolean | optional | Send invitation email to all newly created invitations (default: false) |
Response Fields
| Field | Type | Description |
|---|---|---|
| invited | array | Candidates who received a new invitation — includes email, invite_token, invite_url |
| skipped | array | Candidates skipped with a reason (already_invited | missing_email | error) |
POST /api/v1/public/assessments/senior-backend-screen/invites/bulk/
Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
{
"candidates": [
{ "email": "alice@example.com", "name": "Alice Chen", "role": "Senior Backend Engineer" },
{ "email": "bob@example.com", "name": "Bob Smith", "role": "Senior Backend Engineer" },
{ "email": "jane@example.com" }
],
"send_email": true
}Example Response
{
"invited": [
{
"email": "alice@example.com",
"invite_token": "a1b2c3d4-...",
"invite_url": "https://praxicraft.com/take/a1b2c3d4-..."
},
{
"email": "bob@example.com",
"invite_token": "e5f6a7b8-...",
"invite_url": "https://praxicraft.com/take/e5f6a7b8-..."
}
],
"skipped": [
{ "email": "jane@example.com", "reason": "already invited" }
]
}https://praxicraft.com/api/v1/public/invites/:token/Get Invitation Status
Returns the current status and metadata for a single invitation. Use this to poll pending invitations from your ATS without pulling the full scored result.
Query / Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| token | uuid | required | The invite_token from the create invitation response |
Response Fields
| Field | Type | Description |
|---|---|---|
| invite_token | uuid | Unique token for this invitation |
| string | Candidate email address | |
| name | string|null | Candidate name if provided |
| role | string|null | Job role the candidate was invited for |
| status | string | pending | started | completed | expired |
| assessment | object | { slug, title } — the assessment this invitation belongs to |
| created_at | ISO 8601 | When the invitation was created |
| expires_at | ISO 8601 | Invitation expiry timestamp |
| started_at | ISO 8601|null | When the candidate started the session |
| completed_at | ISO 8601|null | When the candidate completed the session |
| reminded_at | ISO 8601|null | Timestamp of the last reminder email sent |
GET /api/v1/public/invites/c7b3e2a1-.../ Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Example Response
{
"invite_token": "c7b3e2a1-1234-5678-abcd-ef0123456789",
"email": "jane.doe@example.com",
"name": "Jane Doe",
"role": "Senior Backend Engineer",
"status": "started",
"assessment": {
"slug": "senior-backend-screen",
"title": "Senior Backend Engineer Screen"
},
"created_at": "2025-03-15T09:00:00Z",
"expires_at": "2025-03-22T09:00:00Z",
"started_at": "2025-03-15T14:00:00Z",
"completed_at": null,
"reminded_at": null
}https://praxicraft.com/api/v1/public/invites/:token/remind/Send Reminder
Re-sends the invitation email to the candidate. Only valid for invitations in `pending` or `started` status. Returns 400 if the invitation is expired or already completed.
Query / Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| token | uuid | required | The invite_token from the create invitation response |
Response Fields
| Field | Type | Description |
|---|---|---|
| message | string | Confirmation that the reminder was dispatched |
POST /api/v1/public/invites/c7b3e2a1-.../remind/ Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Example Response
{
"message": "Reminder sent."
}https://praxicraft.com/api/v1/public/invites/:token/Cancel Invitation
Permanently deletes a pending invitation. Returns 400 if the candidate has already started or completed the assessment.
Query / Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| token | uuid | required | The invite_token to cancel |
DELETE /api/v1/public/invites/c7b3e2a1-.../ Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Example Response
HTTP/1.1 204 No Content
https://praxicraft.com/api/v1/public/invites/List All Invitations
Returns a global list of all candidate invitations across all assessments in your organisation. Paginated.
Query / Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| cursor | string | optional | Opaque pagination cursor — pass the value from `next` to fetch the next page |
| page_size | integer | optional | Results per page, max 100 (default: 20) |
Response Fields
| Field | Type | Description |
|---|---|---|
| invite_token | uuid | Unique token for this invitation |
| assessment_title | string | Title of the assessment |
| assessment_slug | string | Slug of the assessment |
| string | Candidate email | |
| candidate_name | string|null | Candidate name if provided at invite time |
| role | string|null | Job role the candidate was invited for |
| status | string | pending | started | completed | expired |
| sent_at | ISO 8601|null | When the invite email was dispatched |
| created_at | ISO 8601 | When the invitation record was created |
| expires_at | ISO 8601 | Invitation expiry timestamp |
GET /api/v1/public/invites/ Authorization: Bearer ct_live_xxxxxxxxxxxxxxxx
Example Response
{
"next": "https://app.praxicraft.io/api/v1/public/invites/?cursor=cD0yMDI1LTA0...",
"previous": null,
"results": [
{
"invite_token": "c7b3e2a1-...",
"assessment_title": "Senior Backend Engineer Screen",
"assessment_slug": "senior-backend-screen",
"email": "jane@example.com",
"candidate_name": "Jane Doe",
"role": "Senior Backend Engineer",
"status": "completed",
"sent_at": "2025-03-15T09:00:00Z",
"created_at": "2025-03-15T08:55:00Z",
"expires_at": "2025-03-22T08:55:00Z"
}
]
}