Skip to main content

The REST API

A versioned headless API with keys, CORS, and OpenAPI schema.

Written by Traian

Your board has a headless REST API served on its own domain at /api/v1. Use it to build custom frontends, sync jobs from an ATS, pull applications into your own tooling, or wire the board into automation platforms. It covers jobs (including create, update, publish), employers, your taxonomy, applications, candidates, job-alert subscribers, and per-job analytics.

To manage access: in the sidebar, open Distribution and click API.

The API page with the API keys card, the allowed frontend origins card, and the Using the API card

Create an API key

  1. In the sidebar, open Distribution and click API.

  2. In the API keys card, click Create key.

  3. Enter a Name that says what will use the key (for example "Zapier integration" or "Company website"). One key per integration makes revoking painless later.

  4. Choose an Environment: Live for real integrations, Test for experiments (test keys can read everything but cannot write, see below).

  5. Click Create key.

  6. A dialog titled Your new API key shows the full key exactly once. Click Copy and store it in a password manager or your deployment secrets, then click Done.

easyboard stores only a hash of the key, never the key itself, so it cannot be shown again. If you lose it, revoke it and create a new one. After creation the key appears in the list with its name, a Live or Test badge, its prefix (something like ezb_live_a1b2c3d4), and its created and last-used dates. The "last used" date is your quickest check that an integration is actually calling the API.

Live keys vs test keys

Keys look like ezb_live_... or ezb_test_.... They hit the same board and the same real data; the difference is that test keys are read-only. Any POST, PATCH or DELETE with a test key returns HTTP 405 with error code read_only_key. Use a test key while exploring the API so a script mistake cannot modify your board.

Make your first request

Every request needs an Authorization: Bearer header. The Using the API card shows your board's exact Base URL with a copy button; it is your board's domain plus /api/v1. A good first call is GET /me, which returns the board the key belongs to:

curl https://YOUR-BOARD-DOMAIN/api/v1/me \  -H "Authorization: Bearer ezb_live_YOUR_KEY"

Then list your jobs:

curl "https://YOUR-BOARD-DOMAIN/api/v1/jobs?status=published&per=10" \  -H "Authorization: Bearer ezb_live_YOUR_KEY"

GET /jobs returns jobs in all statuses and supports the filters status, q (matches title and company name), remote, work_mode, employer_id, category_id and job_type_id, plus page and per for pagination. Responses include a meta object with paging info.

Create and publish a job

POST to /jobs with a JSON body. You must provide either an employer_id (an existing employer on your board) or a company_name. New jobs are drafts by default; send "status": "published" to go live immediately, or call POST /jobs/{id}/publish later (publish and unpublish are both idempotent, calling them twice is safe). Published jobs get an expiry 30 days out unless you pass expires_in_days.

curl -X POST https://YOUR-BOARD-DOMAIN/api/v1/jobs \  -H "Authorization: Bearer ezb_live_YOUR_KEY" \  -H "Content-Type: application/json" \  -d '{    "title": "Senior React Developer",    "company_name": "Acme Corp",    "location": "Berlin",    "description": "<p>What you will do...</p>",    "status": "published"  }'

What else the API covers

  • GET /jobs/{id}, PATCH /jobs/{id} (partial update), DELETE /jobs/{id}, POST /jobs/{id}/publish, POST /jobs/{id}/unpublish.

  • GET /applications and GET /applications/{id}: applications received on your board; the detail endpoint includes a pre-signed cv_url for the CV file, valid for 10 minutes.

  • GET /candidates and GET /candidates/{id}: candidate profiles, also with a 10-minute pre-signed cv_url on the detail.

  • GET /analytics/jobs: per-job views, apply clicks and apply rate.

  • GET /job-alerts: your job-alert subscribers.

  • GET /job-types, GET /categories, GET /tags: your board's taxonomy, so you can map IDs when creating jobs.

  • GET /employers, POST /employers, GET /employers/{id}.

For the full request and response schemas, click OpenAPI spec in the Using the API card. It opens /api/v1/openapi.json, a machine-readable spec of your board's API that you can import into Postman, Insomnia or Swagger UI. The spec itself is public and needs no key.

Calling the API from a browser (CORS)

By default the API is server-to-server only: browsers block cross-origin JavaScript calls to it. If you are building a frontend that calls the API directly from the visitor's browser, allow its origin:

  1. In the Allowed frontend origins card, enter one origin per line, for example https://jobs.example.com. Use exact origins: scheme plus host, no paths and no wildcards.

  2. Click Save origins.

Leave the box empty to keep the API server-to-server only. A word of caution: any key you ship in browser JavaScript is visible to visitors, so if you must call from a browser, use a test (read-only) key and keep live keys on your server.

Limits, errors, and revoking

  • Rate limit: 600 requests per minute per key. Beyond that you get HTTP 429 with code rate_limited; back off and retry.

  • Errors are always JSON shaped { "error": { "code", "message", "fields" } } with a matching HTTP status. Validation failures (422) list the offending fields in fields.

  • Wrong board: a key only works on the board that created it. Using it against another board's domain returns 401.

  • Revoking: click Revoke next to a key and confirm with Revoke key. Any integration using it stops working immediately and this cannot be undone. Revoked keys stay in the list, greyed out, as an audit trail.

The API pairs naturally with webhooks: webhooks tell your system the moment something happens, and the API lets you fetch the details or write changes back. For a no-code path into thousands of apps, see Connect Slack, Discord, and Zapier.

Did this answer your question?