Verify Ref Logo

VerifyRef API · v2025-05-19

Find recruits, then verify them — one REST API.

Upload resumes and AI-match candidates to a job (free), then run reference checks, video interviews, or employee surveys. Signed webhooks, sandbox keys, and OpenAPI — pay per use, credits never expire.

Prefer a no-code ATS hookup? Sign up, then open Dashboard → ATS integrations to connect Bullhorn, Zoho, SAP, Greenhouse, or Lever via Merge. (Coming soon)

Why teams switch to VerifyRef

  • Talent pool first — upload resumes and AI-match to a JD for free, then verify shortlists
  • One API call replaces manual chasing — consent, reminders, and collection are automated
  • ~95% reference response rate with built-in 3- and 7-day reminders
  • AI sentiment scoring and red-flag detection on every response
  • Pay per use — no monthly subscription needed like Xref or Referoo
  • Sandbox keys (rc_test_) let you dry-run the full flow for free

Compare pricing and features on our alternatives page. Prefer MCP for agent hosts? See AI agents & MCP.

Setup checklist

Copy this sequence when scaffolding an integration or guiding a setup assistant:

  1. Create a sandbox API keySign up at verifyref.com, then open Dashboard → Developer settings and create an rc_test_ key (free, no emails sent).
  2. Validate the keyGET /api/v1/account with Authorization: Bearer rc_test_... to confirm the key works.
  3. Upload resumes (optional)POST /api/v1/talent-pool/candidates with a PDF/DOCX resume — free, no credits.
  4. Match to a job (optional)POST /api/v1/talent-pool/match with a jobDescription to get top fits with scores.
  5. Create a reference checkPOST /api/v1/checks with candidate details (or candidateId), references, questionnaireId or inline questions, optional externalId + externalSource, and Idempotency-Key.
  6. Register a webhookPOST /api/v1/webhooks with url + events (e.g. check.completed), or use the dashboard after signing in.
  7. Verify inbound signaturesValidate X-VerifyRef-Signature (HMAC-SHA256) on every inbound webhook POST.
  8. Write results to your ATSOn check.completed, use externalId to match the ATS record and store dashboardUrl and reportUrl.

What you can build

Agent hiring workflows

Upload resumes, match to a job description, shortlist, then create a reference check — via REST or MCP.

ATS automations

Fire a check from Bullhorn, Zoho, Greenhouse, or your homegrown ATS the moment a candidate hits the “Reference” stage.

Screening & surveys

Create AI video interviews or employee surveys from the same API key and credit wallet. Exit interviews are dashboard-only today.

Quick start

  1. Grab a sandbox key. Sign up free, then open Dashboard → Developer settings (requires login) and create an rc_test_ key — free, no credits charged, no real emails sent.
  2. Create a check. Pass externalId + externalSource so we can correlate the result back to your ATS record. Set questionnaireId to a template ID from Templates in the dashboard.
  3. Listen for webhooks. Register a URL once; we POST signed events as the check progresses.

cURL — create a check (sandbox)

curl -X POST https://verifyref.com/api/v1/checks \
  -H "Authorization: Bearer rc_test_..." \
  -H "Idempotency-Key: ats-app-12345" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "candidateName": "Jane Doe",
    "candidateEmail": "jane@example.com",
    "externalId": "12345",
    "externalSource": "bullhorn",
    "metadata": { "requisitionId": "REQ-99" },
    "questionnaireId": "YOUR_TEMPLATE_ID",
    "references": [
      { "name": "Ref Name", "email": "ref@example.com", "relationship": "Manager" }
    ]
  }'

Node — verify an inbound webhook

import crypto from "node:crypto";

export function verifyVerifyRef(rawBody: string, signature: string, secret: string) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Authentication

Every request uses a Bearer token in the Authorization header. Generate keys in Dashboard → Developer settings (requires login) — only the team owner can create or revoke them. There is no public API for creating or rotating keys; manage them in the dashboard.

Authorization: Bearer rc_live_7d8f...

rc_live_…

Live keys. Each created check bills 1 credit and sends real emails to candidates and references.

rc_test_…

Sandbox keys. Free, no credits charged, no emails sent. Use these in development, CI, and integration tests.

Keep secrets server-side. Never embed an API key in a browser, mobile app, or public repo. Rotate immediately if a key is exposed.

Base URL & versioning

https://verifyref.com/api/v1

All examples on this page use VerifyRef's production API host (https://verifyref.com). API keys work against this URL whether you read these docs locally or on verifyref.com — examples never use a dev-only host.

Every response includes an X-VerifyRef-Version header so you can pin behavior. Breaking changes always ship under a new version date.

Idempotency

Network retries are inevitable. Send the same Idempotency-Key header on POST /checksand we'll return the original check instead of creating a duplicate.

  • Use a stable, unique value per logical request (e.g. your ATS application ID).
  • Replays return the same response shape with idempotentReplay: true.
  • Keys are scoped per team; rotate freely between live and sandbox.

Endpoints

GET/account

Returns your team name and live credit balance. Use it to validate an API key before kicking off a batch job.

{ "data": { "team": "Acme Corp", "credits": 150 } }
GET/checks

List your team's checks with pagination and filters. Combine externalId + externalSource to find the check matching a record in your ATS.

  • externalId, externalSource — ATS correlation filters
  • statusAWAITING_CONSENT, SENT, IN_PROGRESS, COMPLETED, EXPIRED
  • jobId, createdAfter — narrow by job or ISO timestamp
  • page (default 1), limit (default 20, max 100)
POST/checks

Create a reference check. On live keys this sends the candidate consent email and debits 1 credit. On sandbox keys nothing is emailed and no credit is charged.

Body

  • candidateName * — string
  • candidateEmail * — string
  • references * — array of { name, email, relationship } (skip if candidateProvidedReferences: true)
  • questionnaireId — ID from Templates in the dashboard, or pass questionnaireTitle + questions inline (types: TEXT, TEXTAREA, RATING, MULTIPLE_CHOICE, YES_NO)
  • questionnaireDescription — optional string when creating an inline questionnaire
  • candidateId — link to an existing talent-pool candidate (recommended after match)
  • addToTalentPool — when true and no candidateId, create/find a pool entry from name + email
  • jobId / newJob ({ title, description?, location?, department?, status? } — associate with a job (optional)
  • externalId + externalSource — recommended: pair your ATS record ID with one of bullhorn, zoho_recruit, sap_successfactors, workday, greenhouse, lever, other
  • metadata — free-form JSON echoed back on webhooks

Success (201)

{
  "success": true,
  "checkId": "clx...",
  "status": "AWAITING_CONSENT",
  "jobId": "job_...",
  "externalId": "12345",
  "externalSource": "bullhorn",
  "sandbox": false
}
GET/checks/:id

Full check detail, including each reference response, AI sentiment, red-flag scores, and signed dashboard / PDF report URLs. reportUrl accepts the same Bearer API key.

{
  "data": {
    "id": "clx...",
    "status": "COMPLETED",
    "candidate": { "name": "John Doe", "email": "john@example.com" },
    "externalId": "12345",
    "externalSource": "bullhorn",
    "metadata": { "requisitionId": "REQ-99" },
    "dashboardUrl": "https://verifyref.com/check/clx...",
    "reportUrl": "https://verifyref.com/api/export/check/clx...",
    "references": [
      {
        "name": "Jane Smith",
        "relationship": "Manager",
        "status": "COMPLETED",
        "sentiment": { "score": 0.9, "label": "POSITIVE", "analysis": "..." },
        "redFlags": { "score": 0, "flags": [], "analysis": "No red flags." },
        "responses": [{ "question": "Would you hire them again?", "answer": "Yes." }]
      }
    ]
  }
}
PATCH/checks/:id

Update a check after creation. Supported fields:

  • metadata — merge / replace your ATS payload
  • status: "EXPIRED" — close out a check (fires check.status_changed)
  • emailRemindersEnabled — pause the 3-day / 7-day reminders

Talent pool (free)

No credits. Upload resumes, filter, and AI-match candidates to a job description.

POST/talent-pool/candidates

Multipart upload: field resume (PDF or DOCX). AI extracts profile fields and dedupes by email when possible.

cURL — upload resume

curl -X POST https://verifyref.com/api/v1/talent-pool/candidates \
  -H "Authorization: Bearer rc_test_..." \
  -F "resume=@./candidate.pdf"
GET/talent-pool/candidates

List/filter candidates. Query params:

  • search, location
  • skills, certifications (arrays)

Also: GET/PATCH/DELETE /talent-pool/candidates/:id, POST /talent-pool/candidates/:id/summary (regenerate AI summary), GET /talent-pool/filters (distinct skills / certs / locations).

POST/talent-pool/match

Body: { "jobDescription": "..." }. Returns top matches with fitScore and fitSummary.

Jobs, templates & credits

GETPOST/jobs

List or create jobs. POST body: title (required), optional description, location, department, status (OPEN | CLOSED). Job update/close is dashboard-only today.

GET/templates

List questionnaire templates for your team. Template create/edit is available in the dashboard (or by saving a check questionnaire as a template).

POST/credits/purchase

Buy packs 5 | 20 | 50 | 100. Optional currency: USD (default) or AUD.

  • When MPP is configured, agents may receive HTTP 402 with a Shared Payment Token challenge.
  • Otherwise (or as fallback) the response includes a Stripe checkoutUrl for the user to complete payment.

Video interviews & surveys

GETPOST/video-interviews+ GET /:id

Create an AI video interview invitation (1 credit on live keys). Requires candidateId from the talent pool, title, and 1–12 questions with text + order. Optional jobId, description.

GETPOST/surveys+ GET /:id

Create an employee survey. Body: title, recipients[] ({ email, name? }), questions[], optional anonymous. Credits: 1 per 2 recipients (minimum 1).

Webhooks CRUD

Requires a prior credit purchase on the team. Full event docs are in Webhooks below.

GETPOST/webhooks

POST body: url (HTTPS required), events (non-empty array of event names). Response includes secret once — store it; it is not shown again.

{
  "url": "https://example.com/hooks/verifyref",
  "events": ["check.completed", "email.bounced"]
}

Also: PATCH /webhooks/:id (active, events), DELETE /webhooks/:id, POST /webhooks/:id/test.

Webhooks

Register HTTPS endpoints in Dashboard → Developer settings (requires login) or via POST /webhooks. We POST a signed JSON payload for every subscribed event, retry on failure with exponential backoff, and surface delivery status in your dashboard.

Events

check.created

A check was created (API or dashboard).

check.consent_given

Candidate gave consent; reference emails are about to go out.

check.status_changed

Any status transition (consent → sent → completed → expired).

reference.responded

A reference submitted their questionnaire (fires per reference).

check.completed

Every reference has responded; AI analysis is final.

email.bounced

A candidate or reference email bounced — action may be required.

Payload

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "event": "check.completed",
  "timestamp": "2026-05-20T10:30:00Z",
  "data": {
    "checkId": "clx...",
    "candidateName": "Jane Doe",
    "candidateEmail": "jane@example.com",
    "status": "COMPLETED",
    "externalId": "12345",
    "externalSource": "bullhorn",
    "metadata": { "requisitionId": "REQ-99" },
    "dashboardUrl": "https://verifyref.com/check/clx...",
    "reportUrl": "https://verifyref.com/api/export/check/clx...",
    "completedAt": "2026-05-20T10:30:00Z"
  }
}

Headers: X-VerifyRef-Event, X-VerifyRef-ID, X-VerifyRef-Signature (HMAC-SHA256 of the raw body). Treat X-VerifyRef-ID as the dedup key.

Test before you ship

Point a webhook at https://verifyref.com/api/webhooks/echo and hit “Send test event” in the dashboard. The echo endpoint always returns HTTP 200 and confirms receipt via received: true, event, eventId, hasSignature, and bodyBytes — it does not echo the request body back (by design, for security).

Delivery contract: HTTPS endpoint, respond 2xx within 10 seconds, idempotent by X-VerifyRef-ID. We retry up to 3 times with exponential backoff and persist the last 25 attempts per endpoint.

Errors & rate limits

Errors always return JSON in the shape { "error": { "code", "message", "details?" } }. The v1 rate limit is 100 requests/minute per API key.

400Body failed schema validation. Inspect `details.fieldErrors`.
401Missing or unknown Bearer token.
402Team is out of credits — purchase a pack from billing.
403API key is valid but cannot access this resource.
404Resource does not exist or belongs to another team.
409A check with this externalId + externalSource already exists.
429Slow down; respect retry-after when present.
500Something went wrong on our side — safe to retry.

Dashboard-only features

These product features are available in the VerifyRef dashboard but are not exposed on the public REST API (v1) today:

  • Exit interviews — same credit model as employee surveys (1 credit per 2 recipients); create and analyze in the dashboard. See Exit Interviews.
  • Voice reference completion — referees can optionally complete feedback via an AI voice conversation on the questionnaire link; written responses remain the default.
  • API key management — create and revoke keys only in Developer settings (no key CRUD API).
  • Template & job editing — API can list templates and create/list jobs; full edit UX is in the dashboard.

For AI assistants & agents

Building a setup assistant on top of VerifyRef? Anchor on these public, crawlable resources (no login required):

Dashboard URLs (/team/api, /team/integrations) require the user to sign in. For unattended setup, use the REST API or MCP with a key the user provides, or direct them to /sign-up first. Default to sandbox keys (rc_test_) when scaffolding — no credits charged, no emails sent.