Recruit100x API v1
Quickstart
Create a test key, create a role, listen for events, invite a candidate and simulate a finished interview — in about 10 minutes, without sending a real email or using a credit.
Every sample below runs as written against test mode: set RECRUIT_API_KEY to a test key (r100x_test_…) and the same calls work later with a live key. Each call answers JSON.
1. Create a test key
In Recruit100x, open Settings › Integrations › API keys › Create key, choose Mode: Test and the permissions you need (add Create roles for step 2). The key is shown once. Check it:
curl
curl -sS "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/me" \
-H "Authorization: Bearer $RECRUIT_API_KEY"2. Create a role
Send the job description as text (or "jd": {"mode": "url", "url": …} for a job posting link). The role starts as a draft while its interview guide is drafted.
Open-link default. New roles get your workspace's open-link policy, which is open unless you changed it. Send "open_link": {"policy": "invite_only"} if your system decides who is eligible.curl
curl -sS -X POST "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/roles" \
-H "Authorization: Bearer $RECRUIT_API_KEY" \
-H "Idempotency-Key: create-role-req-1042" \
-H "Content-Type: application/json" \
-d '{
"jd": { "mode": "paste", "text": "Payroll Lead\nRun payroll for 300 people across three US states. You own the close calendar, the year-end filings and the audits." },
"client_label": "Acme Corp",
"location": { "country": "US" },
"external_ref": "req-1042",
"open_link": { "policy": "invite_only" }
}'Node
const base = process.env.RECRUIT_BASE || "https://www.recruit100x.com";
const res = await fetch(`${base}/api/v1/roles`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RECRUIT_API_KEY}`,
"Idempotency-Key": "create-role-req-1042-node",
"Content-Type": "application/json",
},
body: JSON.stringify({
"jd": { "mode": "paste", "text": "Payroll Lead\nRun payroll for 300 people across three US states. You own the close calendar, the year-end filings and the audits." },
"client_label": "Acme Corp",
"location": { "country": "US" },
"external_ref": "req-1042",
"open_link": { "policy": "invite_only" }
}),
});
console.log(JSON.stringify(await res.json()));Python
import json, os, urllib.request
base = os.environ.get("RECRUIT_BASE", "https://www.recruit100x.com")
body = {
"jd": { "mode": "paste", "text": "Payroll Lead\nRun payroll for 300 people across three US states. You own the close calendar, the year-end filings and the audits." },
"client_label": "Acme Corp",
"location": { "country": "US" },
"external_ref": "req-1042",
"open_link": { "policy": "invite_only" }
}
req = urllib.request.Request(
base + "/api/v1/roles",
data=json.dumps(body).encode(),
method="POST",
headers={
"Authorization": "Bearer " + os.environ["RECRUIT_API_KEY"],
"Idempotency-Key": "create-role-req-1042-python",
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(req) as res:
print(json.dumps(json.load(res)))Keep role.id (ROLE_ID below). guide_status is drafting; a person on your team approves the guide in the dashboard (or from the approval email), then the role becomes active. In test mode the guide is approved by itself about 10 seconds later.
3. Listen for events
Subscribe a webhook with "api_version": "2026-11-01" to receive role.ready (the guide is approved — you can invite) and report.ready. The answer carries the signing secret, shown only once.
curl
curl -sS -X POST "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/hooks" \
-H "Authorization: Bearer $RECRUIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "'"$HOOK_URL"'", "events": ["role.ready", "report.ready"], "api_version": "2026-11-01" }'Node
const base = process.env.RECRUIT_BASE || "https://www.recruit100x.com";
const res = await fetch(`${base}/api/v1/hooks`, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.RECRUIT_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ url: process.env.HOOK_URL, events: ["role.ready", "report.ready"], api_version: "2026-11-01" }),
});
// Keep the secret: it signs every delivery and is shown only here.
console.log(JSON.stringify(await res.json()));Python
import json, os, urllib.request
base = os.environ.get("RECRUIT_BASE", "https://www.recruit100x.com")
body = {"url": os.environ["HOOK_URL"], "events": ["role.ready", "report.ready"], "api_version": "2026-11-01"}
req = urllib.request.Request(
base + "/api/v1/hooks",
data=json.dumps(body).encode(),
method="POST",
headers={"Authorization": "Bearer " + os.environ["RECRUIT_API_KEY"], "Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as res:
print(json.dumps(json.load(res))) # keep the secret: it is shown only hereSee Webhooks for every event and for verifying signatures.
4. Invite a candidate
With "delivery": "return_link" you deliver the link yourself: each invited row carries screen_url once. (With "recruit100x" we email the candidate and send a reminder.)
curl
curl -sS -X POST "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/roles/$ROLE_ID/invites" \
-H "Authorization: Bearer $RECRUIT_API_KEY" \
-H "Idempotency-Key: invite-app-77" \
-H "Content-Type: application/json" \
-d '{
"delivery": "return_link",
"candidates": [
{ "full_name": "Sam Rivera", "email": "sam.rivera@example.com", "external_ref": "app-77" }
]
}'Node
const base = process.env.RECRUIT_BASE || "https://www.recruit100x.com";
const res = await fetch(`${base}/api/v1/roles/${process.env.ROLE_ID}/invites`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RECRUIT_API_KEY}`,
"Idempotency-Key": "invite-app-77-node",
"Content-Type": "application/json",
},
body: JSON.stringify({
"delivery": "return_link",
"candidates": [
{ "full_name": "Sam Rivera", "email": "sam.rivera@example.com", "external_ref": "app-77" }
]
}),
});
// With "return_link", each invited row carries screen_url once — send it to the candidate yourself.
console.log(JSON.stringify(await res.json()));Python
import json, os, urllib.request
base = os.environ.get("RECRUIT_BASE", "https://www.recruit100x.com")
body = {
"delivery": "return_link",
"candidates": [
{ "full_name": "Sam Rivera", "email": "sam.rivera@example.com", "external_ref": "app-77" }
]
}
req = urllib.request.Request(
base + "/api/v1/roles/" + os.environ["ROLE_ID"] + "/invites",
data=json.dumps(body).encode(),
method="POST",
headers={
"Authorization": "Bearer " + os.environ["RECRUIT_API_KEY"],
"Idempotency-Key": "invite-app-77-python",
"Content-Type": "application/json",
},
)
with urllib.request.urlopen(req) as res:
print(json.dumps(json.load(res)))5. Simulate the interview
In test mode screen_url opens a test page (/test/screen/{token}) with Simulate completion: it sends screen.completed, then report.ready with a sample report, to your test webhooks. Then read the report:
curl
curl -sS "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/roles/$ROLE_ID/reports?state=ready" \
-H "Authorization: Bearer $RECRUIT_API_KEY"curl
curl -sS "${RECRUIT_BASE:-https://www.recruit100x.com}/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $RECRUIT_API_KEY"Node
const base = process.env.RECRUIT_BASE || "https://www.recruit100x.com";
const res = await fetch(`${base}/api/v1/reports/${process.env.REPORT_ID}`, {
headers: { Authorization: `Bearer ${process.env.RECRUIT_API_KEY}` },
});
console.log(JSON.stringify(await res.json()));Python
import json, os, urllib.request
base = os.environ.get("RECRUIT_BASE", "https://www.recruit100x.com")
req = urllib.request.Request(base + "/api/v1/reports/" + os.environ["REPORT_ID"], headers={"Authorization": "Bearer " + os.environ["RECRUIT_API_KEY"]})
with urllib.request.urlopen(req) as res:
print(json.dumps(json.load(res)))Next: Authentication and scopes, Invites, Errors.