Product

Hiring API: A REST + Bearer Token Pattern for Recruiting Integrations

ClarityHire Team(Editorial)6 min read

Why you need a REST API

Most modern ATS platforms expose data only through webhooks and a native UI. That works if you have 20 people and a single process. But the moment you want to:

  • Sync candidates to your HR system (BambooHR, Workday) that doesn't have a pre-built integration
  • Pull reports into your data warehouse for custom analytics
  • Bulk-import candidates from an old system
  • Build a custom dashboard that your team prefers over the native UI
  • Automate tasks with Zapier or Make.com without writing code

...you need a public REST API.

A REST API is the lingua franca of SaaS integration. Any tool that speaks HTTP can talk to it. Zapier, Make, n8n, Pipedream, custom Python scripts, mobile apps, your own dashboards — all of them can read and write data with a simple authentication token.

The bearer token pattern

The simplest secure API pattern is bearer tokens: you issue each user an API key, they include it in the Authorization: Bearer YOUR_KEY header, and every request authenticates against that key.

This is how Stripe, GitHub, Slack, and most modern APIs work. It's easy to revoke (delete the key), easy to rotate (generate a new one), and easy to scope (issue different keys with different permissions).

curl -H "Authorization: Bearer sk_live_abc123xyz" \
  https://api.clarityhire.com/v1/candidates?job_id=j_engineering_2026

Compare that to username/password or OAuth: bearer tokens are stateless (no session database), can be invalidated instantly, and let you audit which key made which request.

Scopes and permissions

A security best practice: don't issue tokens with full read-write access to everything. Instead, use scopes.

candidates:read       # Can list and view candidates
candidates:write      # Can move candidates, add notes
tests:read            # Can view test results
tests:write           # Can create and edit tests
jobs:read             # Can list jobs
webhooks:manage       # Can create/delete webhooks

When a third-party developer requests API access (say, an HRIS provider integrating with your platform), you issue them a token with only candidates:read and candidates:write. They can't see your billing data or modify interview questions.

Scopes also protect against accidental damage. If an integration script has a bug and starts deleting candidates, you spot it faster if the script should only have candidates:read.

Webhooks vs. polling

Two patterns for keeping data in sync:

Webhooks (event-driven):

POST https://your-system.com/webhook/clarityhire
{
  "event": "candidate.stage_changed",
  "data": {
    "candidate_id": "c_123",
    "old_stage": "screening",
    "new_stage": "assessment",
    "timestamp": "2026-05-21T14:30:00Z"
  }
}

When something happens in ClarityHire, it posts to your endpoint. You process it immediately. Fast, efficient, no polling overhead.

Polling (pull-based):

GET https://api.clarityhire.com/v1/candidates?job_id=j_123&updated_since=2026-05-21T00:00:00Z

You periodically (every 5 minutes, every hour) ask ClarityHire "what changed?" and process the response. Simpler to implement if your system doesn't expose an HTTP endpoint, but slower and noisier.

Best practice: webhooks for real-time (stage changes, new applications), polling for periodic syncs (daily export of all candidates for your data warehouse).

Both patterns should support retry logic. Webhooks can fail (network outage, your endpoint down). The API should retry with exponential backoff and let you see failed attempts in a "webhook logs" dashboard.

Rate limits and idempotency

When you expose an API, you need safeguards against abuse and accidental duplicates.

Rate limits: "You can make 1,000 requests per hour per API key." If someone exceeds it, they get a 429 response with a Retry-After header. Zapier and other integration platforms respect these limits automatically.

Idempotency: If a webhook delivery fails, we retry it. But what if the request actually succeeded, but the response timed out? Without idempotency, we'd create a duplicate candidate or move the candidate twice.

Solution: require an Idempotency-Key header on write requests.

curl -H "Authorization: Bearer sk_live_abc123xyz" \
  -H "Idempotency-Key: zap_12345_attempt_1" \
  -X POST https://api.clarityhire.com/v1/candidates \
  -d '{"email": "[email protected]", "job_id": "j_eng"}'

The API stores the key and response. If the same key is used again, it returns the cached response. No duplicates.

Documentation and SDKs

An API is useless without docs. You need:

  1. Endpoint reference: every route, every parameter, every response format
  2. Error codes: what does a 400 mean? a 403?
  3. Webhook event types: full list of events you emit, with example payloads
  4. Code examples: curl, Python, JavaScript snippets for common tasks
  5. Authentication: how to generate and rotate keys

Bonus: publish SDKs for popular languages (Python, JavaScript, Go). Zapier comes with a built-in SDK, but custom integrations benefit from a native client library that handles pagination, retries, and error handling.

Zapier integration: next-level leverage

Zapier connects hundreds of apps without code. Once you expose a REST API, writing a Zapier integration becomes a 1-2 week project instead of a 4-week custom build.

Example Zap:

  • Trigger: "New candidate in ClarityHire job 'Senior Backend Engineer'"
  • Action 1: "Add row to Google Sheets"
  • Action 2: "Send Slack message to #hiring"
  • Action 3: "Create contact in Pipedrive"

One Zapier user sets this up with zero coding. Other Zapier users discover it in the Zapier marketplace and adopt it. You've built a 100-integration ecosystem without writing 100 integrations.

How ClarityHire exposes its API

ClarityHire offers /api/v1/* with bearer token authentication, scoped permissions, and webhook support. The reference docs live at api.clarityhire.com/docs. Rate limit: 1,000 requests/hour per key. Idempotent writes with Idempotency-Key header.

Example endpoints:

  • GET /api/v1/candidates — list candidates (supports filtering, pagination)
  • GET /api/v1/candidates/{id} — single candidate
  • POST /api/v1/candidates/{id}/move-stage — stage transition
  • GET /api/v1/webhooks — list your active webhooks
  • POST /api/v1/webhooks — register a new webhook

Webhooks can be filtered by event type, job_id, or organization. The system retries failed deliveries 10 times over 24 hours with exponential backoff.

TL;DR

A public REST API with bearer tokens unlocks integrations. Scope permissions by use case. Prefer webhooks for real-time sync, polling for batch exports. Enforce idempotency on writes to prevent duplicates. Document thoroughly, including error codes and examples. Zapier integration is the multiplier: one API enables a thousand use cases without your team coding them.

The investment in API design pays dividends in flexibility and adoption.

apiintegrationszapierwebhooksrecruiting automation

Related Articles