Integrate AssessPro with your ATS, HRIS, or internal systems — REST API v1.
The AssessPro API gives you programmatic access to your applications, positions, and applicants, and lets you invite candidates to assessments directly from your own systems. All endpoints return JSON, respect your organization's data isolation, and are read-scoped to your own data.
Base URL:
https://assesspro.ca/api/v1An interactive OpenAPI (Swagger) explorer is available at /api/v1/docs, or download the raw OpenAPI spec (JSON) to generate client SDKs or import into Postman/Insomnia.
Every request must include your API key in the X-API-Key header:
curl -H "X-API-Key: sk_live_your_api_key_here" \
"https://assesspro.ca/api/v1/applications?limit=10"Requests without a valid key receive 401 Unauthorized. Keys are scoped to your organization — you can only ever see your own data.
Keep your key secret. Never commit it to version control or expose it in client-side code. If a key is compromised, revoke it and generate a new one.
API keys are generated by your AssessPro administrator from inside the app:
1. Sign in as an administrator.
2. Go to API Integration in the sidebar.
3. Click Generate, name the key (e.g. "ATS Integration"), and choose its scopes.
4. Copy the full key immediately — it is shown only once at creation.
If you're a developer integrating on behalf of a client, ask their AssessPro admin to generate a key and send it to you securely.
Admins can generate a sandbox key (prefixed sk_test_ instead of sk_live_) for development. Sandbox keys use the same endpoints and authentication, but:
GET endpoints return fixed, realistic sample data instead of your real recordsPOST /applications returns a successful mock response ("sandbox": true) without sending an email, creating a real applicant, or using a creditBuild and test against a sandbox key, then switch to a live key for production. A key's mode is fixed at creation and visible from its prefix.
Read endpoints are limited to 100 requests per minute; POST /applications is limited to 60 requests per minute. When you exceed a limit you'll receive 429 Too Many Requests.
Best practice: implement exponential backoff on 429 responses, and use limit/offset pagination rather than re-fetching full datasets.
Check API availability. No authentication required — useful for monitoring and connection tests.
{
"status": "healthy",
"version": "1.0.0",
"checks": { "database": "healthy" }
}List applications for your organization, newest first. Includes scores so you can pull assessment results without a second call.
Query parameters:
position_id | optional — filter by position |
stage_id | optional — filter by pipeline stage |
limit | optional — max results (default 100, max 1000) |
offset | optional — skip N results for pagination (default 0) |
Response:
{
"applications": [
{
"id": 1,
"applicant_id": 1,
"position_id": 1,
"overall_score": 78.5,
"application_complete": true,
"requirement_scores": [
{ "name": "Assessments", "score": 81.2, "weight": 40 }
],
"applicant_name": "John Doe",
"applicant_email": "john@example.com",
"position_title": "Software Engineer",
"created_at": "2026-05-20T06:00:00Z",
"updated_at": "2026-05-20T06:00:00Z"
}
],
"limit": 100,
"offset": 0
}Fetch a single application by ID. Returns the same fields as the list endpoint plus applicant_phone.
Errors: 404 if the application doesn't exist or belongs to another organization.
curl -H "X-API-Key: sk_live_xxxxx" \
"https://assesspro.ca/api/v1/applications/1"Create an application and invite a candidate to complete an assessment — the core integration endpoint. One credit is reserved on success; it is refunded if the application is revoked before the candidate completes.
Request body:
name | required — candidate's full name |
email | required — candidate's email address |
assessment_id | required — the assessment to assign |
external_id | optional — your own reference ID, echoed back in responses |
send_email | optional — send the invite email (default true). Set false to deliver the link yourself. |
expires_in_days | optional — link validity (default 7) |
metadata | optional — arbitrary JSON stored with the application |
curl -X POST -H "X-API-Key: sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"email": "jane@example.com",
"assessment_id": 3,
"external_id": "ats-ref-12345"
}' \
"https://assesspro.ca/api/v1/applications"Response (201):
{
"id": 42,
"external_id": "ats-ref-12345",
"assessment_url": "https://assesspro.ca/apply/aBcD1234...",
"status": "requested",
"created_at": "2026-06-10T18:00:00Z"
}Errors: 404 assessment not found | 409 an active application already exists for this email + assessment | 402 insufficient credits.
List positions that have applications from your organization.
Query parameters: status (e.g. active, closed), limit, offset.
{
"positions": [
{
"id": 1,
"title": "Software Engineer",
"status": "active",
"created_at": "2026-05-20T06:00:00Z",
"updated_at": "2026-05-20T06:00:00Z"
}
],
"limit": 100,
"offset": 0
}Fetch a single position. Adds description and location to the list fields. Returns 404 if your organization has no applications for the position.
List your organization's applicants, newest first. Supports limit and offset.
{
"applicants": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"phone": "+1-555-0123",
"created_at": "2026-05-20T06:00:00Z"
}
],
"limit": 100,
"offset": 0
}Webhooks are the recommended alternative to polling. Instead of repeatedly calling the API to check for updates, subscribe to webhooks to receive real-time HTTP POST notifications whenever events happen in AssessPro. This is more efficient, lower-latency, and reduces your API rate limit usage.
Setup steps:
1. Sign in as an administrator.
2. Go to API Integration in the sidebar.
3. Under Webhook Configuration, click Add Webhook.
4. Fill in the webhook details:
5. Before going live: Click Test to preview sample payloads and optionally send test events to your endpoint for validation. The modal shows exactly what your code will receive for each event type.
6. Once your endpoint is verified and ready, enable the webhook by checking Active.
Every delivery attempt — successful and failed — is logged in the Webhook Events table below. You can filter by webhook or export delivery history for auditing.
application.created | A new application is created (direct apply or via POST /applications) |
application.submitted | A candidate submits their application |
stage.changed | An application moves to a new pipeline stage |
assessment.completed | A candidate completes an assessment |
invite.sent | An assessment invite email is sent to a candidate |
When creating a webhook, you can choose how AssessPro authenticates to your endpoint. This is independent of the signing secret — authentication headers control how your endpoint identifies the request source; the signature verifies request integrity.
No Authentication: The webhook sends requests with no additional auth. Use this only if your endpoint is on a private network or behind IP allowlisting.
API Key: Specify a custom header name (e.g., X-API-Key) and value. AssessPro includes this header in every webhook request. Best for simple, static API key scenarios.
X-API-Key: your_key_hereBearer Token: AssessPro sends the token in the Authorization header as a Bearer token. Standard for OAuth2 access tokens or custom token schemes.
Authorization: Bearer your_token_hereBasic Auth: Provide a username and password. AssessPro constructs a standard HTTP Basic Auth header. Avoid over the internet unless using HTTPS; always use HTTPS for production webhooks.
Authorization: Basic base64(username:password)OAuth2: For endpoints protected by OAuth2. Provide a token URL, client ID, and client secret. AssessPro handles the token exchange flow automatically before each webhook delivery.
Every event is delivered as a JSON POST request with this shape:
{
"event": "application.submitted",
"timestamp": "2026-06-13T07:28:43.266114+00:00",
"data": {
"application_id": 787,
"applicant_id": 754,
"applicant_name": "Jane Smith",
"applicant_email": "jane@example.com",
"position_id": 34,
"position_name": "Software Engineer",
"application_stage_id": 13,
"submitted_at": "2026-06-08T05:03:38.212050",
"created_at": "2026-06-08T04:51:58.133913",
"updated_at": "2026-06-10T02:32:25.775758"
}
}Signature Verification (optional but recommended): If you set a signing secret when creating the webhook, every request will include these headers:
X-AssessPro-Event: application.submitted
X-AssessPro-Signature: sha256=f1d4c0e7a2403883bcab9eb16f9e75aaf50a4859e035873abc83e72f2a1ae90fThe signature is an HMAC-SHA256 hex digest of the raw request body (as bytes) using your webhook secret as the key. Always verify signatures to ensure requests come from AssessPro and haven't been tampered with:
import hashlib, hmac
def verify_signature(secret, raw_body, signature_header):
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
# In your webhook handler:
if not verify_signature(WEBHOOK_SECRET, request.body, request.headers.get('X-AssessPro-Signature')):
return 401 # Reject unsigned or invalid requestsNote: Signature verification is independent of your chosen authentication type. Authentication controls how your endpoint identifies AssessPro; the signature verifies the webhook payload integrity.
If your endpoint doesn't return a 2xx response, AssessPro retries up to 3 times total: immediately, then after 30 seconds, then after 5 minutes.
After 10 consecutive failed deliveries, the webhook is automatically marked inactive — re-enable it from the API Integration page once your endpoint is fixed. Every attempt, successful or not, is recorded in the Webhook Events log with its response code and body.
The webhook system is flexible enough for any REST-based endpoint, including these popular ATS and HRIS platforms. When configuring a webhook for one of these, use the pre-built templates or partner-specific authentication options below.
Greenhouse: Leverage Greenhouse's Harvest API to embed assessments in interview plans and sync scores to candidate scorecards. Use Bearer Token authentication with your Greenhouse API key.
Lever: Build pipelines that auto-invite candidates to assessments on stage movements, with assessment scores written back as candidate notes. Integrate via Lever's REST API using Bearer Token authentication.
BambooHR: Trigger assessments when candidates reach hiring stages in BambooHR and write scores back as custom fields. Use API Key authentication with the Accept header pointing to BambooHR endpoints.
Workday: Push assessment scores and candidate status into Workday Recruit automatically. Use OAuth2 authentication for secure handshakes with Workday's REST API.
n8n: Route webhook payloads into n8n workflows for complex, multi-step automations combining AssessPro with dozens of other tools. Use webhook-to-n8n standard Bearer Token or API Key authentication depending on your n8n setup.
For any integration, start by setting up a webhook with the Test feature to verify your endpoint receives the correct payload shape and responds with 200 before enabling production.
200 / 201 | Success / resource created |
400 | Invalid request parameters |
401 | Missing or invalid API key |
402 | Insufficient credits |
404 | Resource not found (or not yours) |
409 | Conflict — duplicate active application |
429 | Rate limit exceeded — back off and retry |
500 | Server error — contact support if persistent |
All errors share one shape:
{ "detail": "Error message describing the issue" }All list endpoints use limit / offset pagination and echo both back in the response. Default page size is 100, maximum 1000. Results are ordered newest first. To walk a full dataset, increase offset by limit until you receive fewer results than limit.
import requests
API_KEY = "sk_live_your_api_key_here"
BASE_URL = "https://assesspro.ca/api/v1"
headers = {"X-API-Key": API_KEY}
# List completed applications with scores
resp = requests.get(f"{BASE_URL}/applications", headers=headers,
params={"limit": 50})
for app in resp.json()["applications"]:
if app["application_complete"]:
print(app["applicant_name"], app["overall_score"])
# Invite a candidate to an assessment
resp = requests.post(f"{BASE_URL}/applications", headers=headers, json={
"name": "Jane Smith",
"email": "jane@example.com",
"assessment_id": 3,
"external_id": "ats-ref-12345",
})
print(resp.json()["assessment_url"])const API_KEY = "sk_live_your_api_key_here";
const BASE_URL = "https://assesspro.ca/api/v1";
const headers = { "X-API-Key": API_KEY };
// List applications
const res = await fetch(`${BASE_URL}/applications?limit=50`, { headers });
const { applications } = await res.json();
// Invite a candidate
const invite = await fetch(`${BASE_URL}/applications`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
name: "Jane Smith",
email: "jane@example.com",
assessment_id: 3,
}),
});
const { assessment_url } = await invite.json();# List applications
curl -H "X-API-Key: sk_live_xxxxx" \
"https://assesspro.ca/api/v1/applications?limit=10"
# List active positions
curl -H "X-API-Key: sk_live_xxxxx" \
"https://assesspro.ca/api/v1/positions?status=active"
# Invite a candidate
curl -X POST -H "X-API-Key: sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{"name":"Jane Smith","email":"jane@example.com","assessment_id":3}' \
"https://assesspro.ca/api/v1/applications"Questions about the API or need help integrating?
Contact Support