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 24- and 72-hour 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 key — Sign up at verifyref.com, then open Dashboard → Developer settings and create an rc_test_ key (free, no emails sent).
  2. Validate the key — GET /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 check — POST /api/v1/checks with candidate details (or candidateId), references, questionnaireId or inline questions, optional externalId + externalSource, and Idempotency-Key.
  6. Register a webhook — POST /api/v1/webhooks with url + events (e.g. check.completed), or use the dashboard after signing in.
  7. Verify inbound signatures — Validate X-VerifyRef-Signature (HMAC-SHA256) on every inbound webhook POST.
  8. Write results to your ATS — On 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
  • status — AWAITING_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 24-hour / 72-hour 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.