Overview
V1 has two public endpoints. Use /public/search to find candidates with a query plus optional filters. Use /public/usage to check your remaining daily quota without spending it.
/public/search/public/usageResults never include contact details
Candidate results carry no email, phone number, or LinkedIn - by design. Use the returned candidateId or cazumeUrl to reach a candidate through the CazVid app or their public profile. Do not attempt to re-identify or contact candidates off-platform.
Authentication
Send your API key with the x-api-key header or as an Authorization: Bearer token. This is the same CazVid Developer API key as the Job Builder API - one key works for both products. Keys belong to an organization; org owners and admins manage them in the app under Profile > Developer API. Plaintext keys are shown once when created and stored hash-only by CazVid. Treat keys as secrets: do not put them in frontend code, mobile apps, screenshots, logs, or support messages.
x-api-key: cazvid_jb_...
Authorization: Bearer cazvid_jb_...
Content-Type: application/jsonSearch candidates
POST /public/search takes a required query (2 to 300 characters) plus optional structured filters. Filters narrow the same candidate pool the in-app recruiter search serves. Send page and pageSize to page through results; pageSize is capped at 25 and page at 100.
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | Required | Natural-language candidate search (2 to 300 characters), for example 'bilingual customer support agent in Mexico City'. |
| location | string | Optional | Optional free-text location filter (city, region, or country), up to 120 characters, for example 'Bogota, Colombia'. |
| remote | boolean | Optional | When true, bias results toward remote-capable candidates. |
| requireVideo | boolean | Optional | When true, only return candidates with a playable video profile. |
| language | string (ISO 639-1) | Optional | Preferred resume language as an ISO 639-1 two-letter code (for example en or es). Results are biased toward this language; it is best-effort, not a strict filter. |
| createdAfter | string (ISO 8601) | Optional | ISO 8601 date-time. Only return candidates whose searchable content was updated after this instant. |
| page | integer | Optional | 1-based page number, 1 to 100. Defaults to 1. |
| pageSize | integer | Optional | Results per page, 1 to 25. Defaults to 10. |
curl -X POST https://aio-backend-prod.cazvid.app/api/v3.0/candidate-search/public/search \
-H "x-api-key: cazvid_jb_..." \
-H "Content-Type: application/json" \
-d '{
"query": "bilingual customer support agent in Mexico City",
"location": "Mexico City, Mexico",
"remote": true,
"requireVideo": true,
"language": "en",
"page": 1,
"pageSize": 10
}'Result shape
Each result is a public, scrubbed candidate profile. Nullable fields are omitted or null when CazVid does not have that data. candidateId is an opaque, stable pc1. token, not a raw platform id and not reversible by callers. cazumeUrl is present only when the candidate has published a public Cazume profile.
| Field | Type | Description |
|---|---|---|
| candidateId | string | Opaque, stable candidate token (pc1....). Use it to reach the candidate through the CazVid app; it is not a raw platform id and is not reversible. |
| displayName | string | null | Candidate display name, with contact info scrubbed. |
| headline | string | null | Resolved current or most-recent job title. |
| summary | string | null | Short experience summary, with contact info scrubbed. |
| topSkills | string[] | Top skills, with contact info scrubbed. |
| matchedSkills | string[] | Subset of top skills that matched the query. |
| matchTier | string | null | Relative match tier for this query when available; treat it as an opaque label. |
| locationName | string | null | Human-readable candidate location. |
| countryCode | string | null | ISO 3166-1 alpha-2 country code, when available. |
| isRemote | boolean | Whether the candidate is remote-capable. |
| language | string | null | ISO 639-1 resume language, when available. |
| hasVideo | boolean | Whether a playable video profile exists. |
| videoUrl | string | null | CazVid-hosted video profile URL, when available. |
| thumbnailUrl | string | null | CazVid-hosted video thumbnail URL, when available. |
| avatarUrl | string | null | CazVid-hosted avatar image URL, when available. |
| cazumeUrl | string | null | Public Cazume profile URL (https://cazvid.com/cazume/<slug>), present only when the candidate has published one. |
| updatedAt | string | null | ISO 8601 timestamp of the candidate's most recent searchable content. |
{
"results": [
{
"candidateId": "pc1.aGVsbG8td29ybGQ",
"displayName": "Maria G.",
"headline": "Bilingual Customer Support Specialist",
"summary": "Five years supporting SaaS customers in English and Spanish.",
"topSkills": ["Customer support", "Zendesk", "Bilingual (EN/ES)"],
"matchedSkills": ["Customer support", "Bilingual (EN/ES)"],
"matchTier": "local",
"locationName": "Mexico City, Mexico",
"countryCode": "MX",
"isRemote": true,
"language": "en",
"hasVideo": true,
"videoUrl": "https://ik.imagekit.io/cazvid/videos/example.mp4",
"thumbnailUrl": "https://ik.imagekit.io/cazvid/thumbs/example.jpg",
"avatarUrl": "https://ik.imagekit.io/cazvid/avatars/example.jpg",
"cazumeUrl": "https://cazvid.com/cazume/maria-g",
"updatedAt": "2026-07-01T12:30:00.000Z"
}
],
"hasMore": true,
"page": 1,
"pageSize": 10
}Pagination
The response wraps the results with pagination metadata. This API paginates on hasMore only - there is no total count.
results- the candidate profiles for this page.hasMore- true when another page exists. Request the next page by incrementingpage.page- the echoed 1-based page number.pageSize- the echoed page size.- There is no total-count field. Do not expect a
totalorcount: keep requesting pages whilehasMoreis true.
Check remaining quota
GET /public/usage returns the calling organization's daily Candidate Search quota. It uses the same authentication as search and does not count against the quota, so you can poll it before a batch to avoid 429 responses. Polling is throttled to 60 requests per minute per API key; exceeding it returns the standard 429 shape with details.period set to minute.
/public/usagecurl https://aio-backend-prod.cazvid.app/api/v3.0/candidate-search/public/usage \
-H "x-api-key: cazvid_jb_..."| Field | Type | Description |
|---|---|---|
| dailyQuota | number | Total successful search calls allowed per organization per UTC day. |
| used | number | Quota-consuming search calls made with this organization's API keys today (UTC). |
| remaining | number | Successful calls left before the quota resets. |
| resetsAt | string (ISO 8601) | ISO 8601 timestamp of the next UTC midnight, when the quota resets. |
| period | "utc_day" | Quota window. Always utc_day in v1. |
{
"dailyQuota": 100,
"used": 12,
"remaining": 88,
"resetsAt": "2026-07-08T00:00:00.000Z",
"period": "utc_day"
}Errors
Error responses use stable errorCode values so integrations do not need to parse prose messages. Every error echoes the request path; 429 responses add retryAfter, the number of seconds until the limit window resets. A 429 from the daily quota carries details.period of utc_day; a 429 from the per-minute burst or usage throttle carries minute.
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Request body failed validation (for example query length, page or pageSize bounds, language format, or createdAfter format). |
| 401 | API_KEY_MISSING | No API key was sent. |
| 401 | API_KEY_INVALID | The key does not exist or cannot be verified. |
| 401 | API_KEY_EXPIRED | The key is past its expiry date. |
| 401 | API_KEY_REVOKED | The key was revoked. |
| 403 | PLAN_REQUIRED | Production API access requires a Platinum plan or higher. |
| 403 | SCOPE_FORBIDDEN | The key does not carry the candidate-search scope. |
| 403 | ORG_ACCESS_DENIED | The key cannot access this organization. |
| 403 | WORKSPACE_ACCESS_DENIED | The workspaceId in the request body does not belong to your API key. |
| 429 | RATE_LIMIT_EXCEEDED | A rate limit was hit: the daily quota (details.period utc_day) or the per-minute burst or usage throttle (details.period minute). |
| 504 | SEARCH_TIMEOUT | The candidate search took too long upstream. Retry the request. |
| 500 | CANDIDATE_SEARCH_API_ERROR | An unexpected server error occurred, or a dependency was unavailable. |
{
"statusCode": 429,
"errorCode": "RATE_LIMIT_EXCEEDED",
"message": "Daily Candidate Search API quota exceeded.",
"details": {
"limit": 100,
"period": "utc_day"
},
"retryAfter": 21600,
"path": "/api/v3.0/candidate-search/public/search"
}Acceptable use
Candidate data is provided to serve the end user's request in front of you, not to be copied or resold. By using this API you agree to the following. These terms may be replaced by formal API terms at general availability.
- No bulk mirroring or redistribution. Do not copy the candidate index into your own store or build a competing directory or dataset from it.
- No retention beyond serving the request. Hold results only as long as needed to answer the request in front of you; do not build a persistent shadow copy of candidate profiles.
- No resale. Candidate profiles and any fields derived from them may not be sold, sublicensed, or redistributed.
- Contact candidates only through CazVid. Results carry no contact details; reach a candidate through their public Cazume profile or the CazVid app, never off-platform.
- No quota circumvention. Do not use multiple keys, organizations, or accounts to evade the per-organization daily quota or the per-minute burst limit.
Limits and behavior
- V1 quota is 100 successful
searchcalls per organization per UTC day. This is a separate quota from the Job Builder API. - A per-organization burst limit of 20 searches per minute protects the shared search backend. Exceeding it returns
429withdetails.periodset tominute. pageSizeis capped at 25 andpageat 100. Requests above those bounds return400 VALIDATION_ERROR.- Results carry no contact details (no email, phone, or LinkedIn) and no raw platform ids. Reach candidates through the CazVid app or their Cazume profile.
- Rotate keys by creating a new key, updating your integration, then revoking the old key. The same key serves the Job Builder API too.
Use from an agent (MCP)
Prefer to drive candidate search from an AI agent instead of raw HTTP? The CazVid MCP server exposes search_candidates (plus list_api_usage) to Claude Code, Claude.ai, ChatGPT, Cursor, and VS Code, using this same API key and daily quota.