Overview
V1 has two public endpoints. Use /public/search to find public job posts with a query plus optional filters. Use /public/usage to check your remaining daily quota without spending it. The OpenAPI contract is served at /public/openapi.json.
/public/search/public/usagePublic job posts, with an apply link and no contact data
Every result is a public CazVid job post. Results never include hiring-manager or recruiter contact details - no email, phone, or LinkedIn. When the job has a public page, the result carries an applyUrl (the CazVid job page where a seeker applies) and a stable slug. Hand a seeker the applyUrl; applying always happens on CazVid.
Authentication
Send your API key with the x-api-key header or as an Authorization: Bearer token. Keys belong to an organization; org owners and admins manage them in the app under Profile > Developer API, and job seekers can create one too. 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. The same key format (cazvid_jb_...) serves every CazVid Developer API family; each key carries only the scopes your plan allows.
x-api-key: cazvid_jb_...
Authorization: Bearer cazvid_jb_...
Content-Type: application/jsonSearch jobs
POST /public/search takes an optional query plus optional structured filters. Send query in plain language (for example 'warehouse jobs in Bogota'), or leave it out to browse by filters alone. Send page and pageSize to page through results; pageSize is capped at 25 and page at 100. Requests above those bounds return 400 VALIDATION_ERROR.
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | Optional | Optional natural-language job search, for example 'warehouse jobs in Bogota'. Omit it to browse by filters alone. |
| location | string | Optional | Optional free-text location filter (city, region, or country), for example 'Bogota, Colombia' or 'Mexico'. |
| remote | boolean | Optional | When true, bias results toward remote jobs. |
| language | string (ISO 639-1) | Optional | Preferred job-post 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 jobs posted after this instant; filters on the posting createdAt. |
| 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/job-search/public/search \
-H "x-api-key: cazvid_jb_..." \
-H "Content-Type: application/json" \
-d '{
"query": "warehouse jobs in Bogota",
"location": "Bogota, Colombia",
"remote": false,
"language": "es",
"page": 1,
"pageSize": 10
}'Result shape
Each result is a public job post. Nullable fields are omitted or null when CazVid does not have that data. When present, slug identifies the job on cazvid.com and applyUrl is the canonical job page a seeker applies through (https://cazvid.com/job/<slug>, or /empleo/<slug> in Spanish); both are null for a job with no public page. No raw platform ids and no contact fields are ever included.
| Field | Type | Description |
|---|---|---|
| title | string | null | Job post title. |
| description | string | null | Job description, with contact details scrubbed and HTML stripped. |
| companyName | string | null | Hiring company name, when available. |
| authorName | string | null | Public display name shown on the job page, when available. |
| jobType | string | null | Job type (for example full-time or part-time), when available. |
| typeOfWork | string | null | Work arrangement classification, when available. |
| isRemote | boolean | Whether the job is remote. |
| remoteWorkScope | string | null | Remote scope (for example country-only or worldwide), when available. |
| locationName | string | null | Human-readable job location. |
| locationCountryCode | string | null | ISO 3166-1 alpha-2 country code, when available. |
| payAmount | number | null | Pay amount, when available. |
| payCurrency | string | null | ISO 4217 currency code for the pay amount, when available. |
| payType | string | null | Pay period (for example hourly or monthly), when available. |
| isNegotiable | boolean | Whether the pay is negotiable. |
| language | string | null | ISO 639-1 language of the job post, when available. |
| occupationTitles | string[] | Occupation titles matched to the job. |
| occupationFamilies | string[] | Occupation families the job belongs to. |
| createdAt | string | null | ISO 8601 timestamp of when the job was posted. |
| refreshedAt | string | null | ISO 8601 timestamp of the job's most recent refresh, when available. |
| slug | string | null | Stable public slug identifying the job on cazvid.com, or null when the job has no public page. |
| applyUrl | string | null | Canonical CazVid job page to apply through (https://cazvid.com/job/<slug>, or /empleo/<slug> in Spanish), or null when the job has no public page. |
| videoUrl | string | null | CazVid-hosted job video URL, when available. |
| thumbnailUrl | string | null | CazVid-hosted job video thumbnail URL, when available. |
{
"jobs": [
{
"title": "Warehouse Operator",
"description": "Join our Bogota distribution center as a warehouse operator...",
"companyName": "Andes Logistics",
"authorName": "Andes Logistics HR",
"jobType": "full-time",
"typeOfWork": "on-site",
"isRemote": false,
"remoteWorkScope": null,
"locationName": "Bogota, Colombia",
"locationCountryCode": "CO",
"payAmount": 1800000,
"payCurrency": "COP",
"payType": "monthly",
"isNegotiable": false,
"language": "es",
"occupationTitles": ["Warehouse Operator", "Logistics Assistant"],
"occupationFamilies": ["Transportation and Logistics"],
"createdAt": "2026-07-01T12:30:00.000Z",
"refreshedAt": "2026-07-08T09:00:00.000Z",
"slug": "warehouse-operator-bogota-andes-logistics",
"applyUrl": "https://cazvid.com/empleo/warehouse-operator-bogota-andes-logistics",
"videoUrl": "https://ik.imagekit.io/cazvid/videos/example.mp4",
"thumbnailUrl": "https://ik.imagekit.io/cazvid/thumbs/example.jpg"
}
],
"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.
jobs- the job posts 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 Job 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/job-search/public/usage \
-H "x-api-key: cazvid_jb_..."| Field | Type | Description |
|---|---|---|
| dailyQuota | number | Total successful search calls allowed per organization per UTC day. Defaults to 500. |
| used | number | Quota-consuming search calls made with this organization's API keys today (UTC). |
| remaining | number | Successful calls left before the quota resets at UTC midnight. |
| 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": 500,
"used": 12,
"remaining": 488,
"resetsAt": "2026-07-11T00: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; a 429 from the per-IP backstop carries minute with details.scope of ip.
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Request body failed validation, for example a wrong field type, an invalid language or createdAfter format, or a page or pageSize above the allowed bounds. |
| 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 | SCOPE_FORBIDDEN | The key does not carry the job-search scope. |
| 429 | RATE_LIMIT_EXCEEDED | A rate limit was hit: the daily quota (details.period utc_day), the per-minute burst or usage throttle (details.period minute), or the per-IP backstop (details.period minute with details.scope ip). |
| 504 | SEARCH_TIMEOUT | The job search took too long upstream. Retry the request. |
| 500 | JOB_SEARCH_API_ERROR | An unexpected server error occurred, or a dependency was unavailable. |
{
"statusCode": 429,
"errorCode": "RATE_LIMIT_EXCEEDED",
"message": "Daily Job Search API quota exceeded.",
"details": {
"limit": 500,
"period": "utc_day"
},
"retryAfter": 21600,
"path": "/api/v3.0/job-search/public/search"
}Acceptable use
Job posts are provided to serve the end user's job search 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 job index into your own store or build a competing job board or dataset from it.
- No retention beyond serving the request. Hold results only as long as needed to answer the search in front of you; do not build a persistent shadow copy of the job index.
- No resale. Job posts and any fields derived from them may not be sold, sublicensed, or redistributed.
- Apply through CazVid. Send seekers to the
applyUrlon cazvid.com; do not scrape around it or redirect applications off-platform. - No quota circumvention. Do not use multiple keys, organizations, or accounts to evade the per-organization daily quota, the per-minute burst limit, or the per-IP backstop.
Limits and behavior
- V1 quota is 500 successful
searchcalls per organization per UTC day. The job-search scope is free and separate from the Job Builder and Candidate Search quotas. - A per-organization burst limit of 30 searches per minute, plus a 60-per-minute per-IP backstop, protects the shared search backend. Exceeding either returns
429withdetails.periodset tominute(the per-IP block addsdetails.scopeofip). pageSizeis capped at 25 andpageat 100. Requests above those bounds return400 VALIDATION_ERROR.- Results are public job posts. They carry an
applyUrlandslugwhen the job has a public page, but no hiring-manager contact details and no raw platform ids. - Rotate keys by creating a new key, updating your integration, then revoking the old key. Each organization can hold up to 10 active keys across all families.
Use from an agent (MCP)
Prefer to drive job search from an AI agent instead of raw HTTP? The CazVid MCP server exposes search_jobs (plus list_api_usage) to Claude Code, Claude.ai, ChatGPT, Cursor, and VS Code, using this same API key and daily quota.