Developers
Jobs API
Send your open roles from your own systems, in one call or one at a time. Free for verified companies.
Before you start
If your roles are on Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio, Teamtailor or Workday, you don't need this: we read those boards automatically. The API is for everything else, or for roles that aren't on your public board. Prefer a spreadsheet? Upload a CSV from your employer dashboard instead.
Claim your company, then create a key under Bulk upload and API. Send it with every request:
Authorization: Bearer vb_live_…Replace all your roles
One call with every open role. With "mode": "full_sync", roles you pushed before that aren't in the batch are closed. A full sync only runs when every job is valid, so a typo can't close your listings.
curl -X POST https://vultboard.com/api/v1/jobs \
-H "Authorization: Bearer vb_live_…" \
-H "Content-Type: application/json" \
-d '{
"mode": "full_sync",
"jobs": [{
"externalId": "ml-eng-1",
"title": "Machine Learning Engineer",
"description": "## What you'll do\n\nTrain and ship models.",
"applyUrl": "https://example.com/careers/ml-eng-1",
"workplace": "hybrid",
"locations": ["London", "Berlin"],
"salary": { "min": 120000, "max": 160000, "currency": "GBP", "period": "year" }
}]
}'The default mode, upsert, adds and updates without closing anything; valid jobs are applied and invalid ones are reported. Up to 5,000 jobs per batch.
{
"created": 1, "updated": 0, "unchanged": 0, "closed": 2,
"skipped": [],
"errors": [{ "index": 3, "externalId": "x", "errors": ["applyUrl: Use an https:// link"] }]
}One role at a time
PUT /api/v1/jobs/:externalIdcreates or updates one role (the same fields, withoutexternalId).DELETE /api/v1/jobs/:externalIdcloses it now.GET /api/v1/jobslists your pushed roles with their public URL, status and when each expires.
Fields
externalId(required): your id for the role. Sending it again updates it.title,description,applyUrl(https) andworkplace("remote", "hybrid", "onsite") are required.descriptionis Markdown, or setdescriptionFormatto"html"to send HTML from your ATS. Everything is sanitised.locations: cities, countries or "Remote (Europe)".employmentType: "full_time", "part_time", "contract", "internship". Defaults to full-time.salary:min,max, a three-lettercurrencyand aperiod("hour", "day", "month", "year").departmentandpublishedAt(ISO date, not in the future) are optional.
How pushed roles are listed
- Each role stays listed for 30 days after it was last sent. Send it again, or run a daily full sync, to keep it live.
- Roles are categorised like every other listing. At companies outside AI and web3, only AI and web3 roles are listed; others come back under
skipped. - Errors look like
{ "error": { "code", "message" } }: 401 for a missing or revoked key, 413 for bodies over 20 MB, 422 for invalid jobs, 429 above 120 requests a minute per key (seeRetry-After).