caferemote

Employer API v1

Create, update and close remote jobs from your own systems. Fields follow schema.org JobPosting, so your existing markup maps across directly.

Authentication

Send Authorization: Bearer <key> on every request. Keys are issued when you redeem an invitation. A key starting cr_test_ is a sandbox key: it validates your job and reports what would happen, and writes nothing.

Base URL: https://www.caferemote.com/api/v1 (HTTPS only). Machine-readable spec: openapi.json.

Rules

  • Fully remote jobs only, in English. Hybrid or on-site wording is rejected.
  • Description of at least 300 characters, at most 100 KB.
  • An https apply link or an apply email.
  • remote.applicantCountries: ISO alpha-2 codes or "WORLDWIDE".
  • The first three jobs of a new employer are reviewed by a person.

Endpoints

MethodPathScopePurpose
PUT/jobs/{externalId}jobs:writeCreate or update (201 or 200)
POST/jobs/bulkjobs:writeUp to 100 jobs in one call
DELETE/jobs/{externalId}jobs:writeClose a job
GET/jobsjobs:readList your jobs, filter by status
GET/jobs/{externalId}jobs:readOne job and its state
GET/taxonomieskeyValid categories, skills and levels
GET/mekeyYour account and key details
POST/invites/redeempublicExchange an invite token for keys
GET/openapi.jsonpublicOpenAPI 3 specification

Create or update a job

The same call creates and updates. Repeat it with the same externalId to change a job. Add an Idempotency-Key header to make retries safe for 24 hours.

curl -X PUT https://www.caferemote.com/api/v1/jobs/job-001 \
  -H "Authorization: Bearer $KEY" \
  -H "Idempotency-Key: abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "job-001",
    "title": "Senior Engineer",
    "description": "<p>At least 300 characters of English text...</p>",
    "applyUrl": "https://acme.example/j/1",
    "remote": { "type": "TELECOMMUTE", "applicantCountries": ["US", "CA"] }
  }'

Bulk upload

POST /jobs/bulk takes up to 100 jobs, each shaped like the single-job body. Each job gets its own result, so one bad job does not block the rest.

Close a job

curl -X DELETE https://www.caferemote.com/api/v1/jobs/job-001 \
  -H "Authorization: Bearer $KEY"

List your jobs

curl "https://www.caferemote.com/api/v1/jobs?status=pending&per_page=50" \
  -H "Authorization: Bearer $KEY"

Fields

Required: externalId, title, description, remote, and one of applyUrl or applyEmail.

Optional: employmentType, salary (min, max, currency, period), datePosted, validThrough, category, skills, experienceLevel, intro, responsibilities, requirements, niceToHave, benefits (up to 40 items each) and a company block.

Tip: send intro and the list fields. Jobs with a short intro and bullet lists read much better and convert more applicants.

Webhooks

We POST an event to your endpoint when a job changes state: job.approved, job.rejected, job.published, job.expired, job.closed. Retries run after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours.

Headers: X-CafeRemote-Event, X-CafeRemote-Delivery and X-CafeRemote-Signature: t=<unix>,v1=<hex>.

Verify with v1 = HMAC-SHA256(secret, "<t>." + rawBody) and reject timestamps older than 5 minutes.

Errors and limits

Errors use application/problem+json (RFC 9457): 401 bad key, 403 scope, 404 not found, 422 validation with errors or reasons, 426 not https, 429 rate limited with Retry-After.

Limit: 60 requests per minute per key. See X-RateLimit-Limit and X-RateLimit-Remaining on every response.

Get remote jobs the moment they are posted

Choose your categories and skills. We push matching jobs to your device. No email, ever.