Docs
Clean, open jobs with GUIDs, kept current. One key, JSON, cursors that never skip. The one thing charged is a full job returned by the full feed; events, updates, companies and counts are free.
curl -s 'https://api.jobmonkey.ai/v1/jobs?country=Canada&limit=2' \
-H 'Authorization: Bearer cb_live_XXXXXXXX'
Try a call from your terminal: get a free key, paste it in place of cb_live_XXXXXXXX, and the page of jobs is yours. 250 jobs a month are free, with no end date.
Start
Start here
A free key to your first page of jobs in five minutes.
Your first sync in three calls
Load once, read events, fetch by GUID. That is the whole loop.
The cursor
One number for every stream, and it never skips.
Held closures and closing_since
A job that left its board is checked before it is called closed.
What the feed does not carry
Five things the ledger leaves out, on purpose.
Fields
Every field of a job and a company, with its type. Fields that begin with ai_ are ours.
Snapshots
A whole country in one file, priced like the pages.
Sizes by country and system
Jobs live and new jobs in 30 days, per country and per ATS, as the nightly counted them.
Routes
| Route | What | Charged |
|---|---|---|
GET /v1/jobs | Full jobs by cursor: a first load cut to countries and systems | every full job in the answer, every time |
POST /v1/jobs | Full jobs by GUID (up to 1,000); closed or unknown GUIDs come back free in `missing` | every full job in the answer, every time; a GUID in `missing` is free |
GET /v1/jobs/count | Open jobs, held closures and companies for a cut | nothing |
GET /v1/events | Job events after a cursor: new, changed (with the new values), closed, reopened | nothing |
GET /v1/updates | Changed fields with their new values: the events stream filtered to `changed` | nothing |
GET /v1/events/count | Events after a cursor, by kind: how far behind a buyer is | nothing |
GET /v1/companies | Companies in GUID order for a cut, or by GUID (`guid=a,b,c`) | nothing |
GET /v1/companies/events | Company changes after a cursor (the same ledger numbers as the job events) | nothing |
GET /v1/search | Title search over open jobs: shape=page (the card) or shape=match (GUIDs for a campaign) | nothing |
GET /v1/snapshots | The newest weekly snapshot: its files, their jobs, bytes and sha256 | nothing for the list |
POST /v1/snapshots/{stamp}/{file} | A 24-hour link to one snapshot file (`everything` or a country); the file's jobs are charged once | the file's jobs, once, at link time; a second link for the same file inside 24 hours is free; the companies file comes free |
GET /v1/health | 200 when every database answers | nothing; no key |
Plans and billing
Prices, the free taste, overage and the spend cap
One thing is charged. Here is how it is counted, capped and cancelled.
Changelog
Fields added or renamed, prices, routes, dated.
Every answer
X-Request-IdX-Units-ChargedRateLimit (limit=10, remaining=n, reset=s)RateLimit-Policy (10;w=1, plus 10;w=86400 on a free key calling a free route)X-Plan-Jobs-Remaining (the full feed and snapshots, when the plan has a cap)X-Account: past_due (while an invoice is unpaid)
Errors are JSON, {"error": {"code": "...", "message": "..."}}, with the status:
| Status | Code | When |
|---|---|---|
| 400 | bad_request | an unknown parameter, a bad cursor, a bad GUID, a number out of range |
| 401 | no_key | no Authorization header |
| 401 | bad_key | unknown, revoked or expired key, or a malformed header |
| 401 | account_off | the account is off (an unpaid invoice past its 7 days); see your invoices |
| 403 | no_scope | the key lacks the route's scope (search is a house scope) |
| 429 | rate_limited | over 10 calls a second on this key; Retry-After: 1 |
| 429 | plan_exhausted | no jobs or calls left on the plan this month, or the day's free-API calls on a free key; Retry-After says when |
Authorization: Bearer cb_live_XXXXXXXX on every route but /v1/health. Times are UTC, ISO 8601. country and system take one value, a comma list (country=Canada,Mexico) or a repeat (country=Canada&country=Mexico); the country is its English name as the data holds it; the system is the ATS name (greenhouse, lever.co, workday, ...): /v1/jobs/count lists the sizes, /docs/sizes shows them.