Wipperoz Orbit public API
Version 1.0.0 · OpenAPI 3.1.0
Base URLs
| Environment | URL |
|---|---|
| Production | https://api.wipperoz.com |
The Orbit public API lets an account render its own jobs on its own site. Wipperoz is the production tool; the employer is the origin. Every job carries an applyLink to the Wipperoz-hosted apply page, which records the candidate's consent — the employer owns the page, Wipperoz owns the transaction.
Authentication
Every request carries an account API key, minted in Orbit → Settings → API keys. Send it either as Authorization: Bearer <key> or in the x-api-key header. A revoked key stops working within one request. Keys are account-scoped: every response is the calling account's jobs, and there is no cross-account read or write.
Two scopes, chosen when the key is minted and fixed for its life:
- jobs:read — the two read endpoints. What a careers site needs. - jobs:write — create, edit, publish and close. Publishing spends the account's credits, so this is deliberately not implied by jobs:read: a key that renders a careers page should not also be able to post ads.
Writing jobs
Creating and publishing are two calls. POST /v1/jobs makes a draft — nothing public, nothing charged — and POST /v1/jobs/{jobId}/publish takes it live and charges the publish fee, once, on first publish. An integration that wants the whole loop without a person calls both.
Editing a published ad stages the new words rather than replacing the ones candidates are applying against; the response says pendingRevision: true, and publishEdits: true promotes them in the same call. The closing date and the match cap are exempt and apply immediately — both exist to stop something.
Retries
Send an Idempotency-Key header on POST requests. A retry with the same key returns the first answer (with Idempotent-Replay: true) instead of creating a second advertisement or taking a second charge; the key is remembered for 24 hours. The same key with a different body is refused with 409. Without the header, two identical creates make two ads.
Rate limits
120 requests per minute per key. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (epoch seconds); a request over the limit is answered 429 with Retry-After. A careers page that syncs incrementally needs a handful of calls an hour; the limit exists to stop a misconfigured loop.
Pagination
GET /v1/jobs returns up to limit jobs (default 50, maximum 100) and a nextCursor. Pass it back as cursor to fetch the next page; null means there is no more. Cursors are opaque and issued by this API only.
Incremental sync
updatedSince returns jobs edited, published or closed at or after the given moment. Expiry is time-based and writes nothing, so a page that syncs by updatedSince alone must read each job's expiresAt itself — or ask for status=published and treat anything missing as gone.
Errors
Every error is the same shape: {"error": {"code", "message", "requestId"}}. Quote the requestId to support.
Endpoints
Jobs
Reading the calling account's published, closed and expired jobs. Drafts never appear here.
Writing jobs
Creating, editing, publishing and closing the account's advertisements. Needs the `jobs:write` scope.