Aller au contenu principal
WipperozWipperoz
Parcourir la documentation

Jobs

Reading the calling account's published, closed and expired jobs. Drafts never appear here.

List the account's jobs

GET /v1/jobs

Published jobs, plus closed and expired ones with their status set, so a careers page can render its own closed state instead of breaking links it already published. Drafts are never returned.

Parameters

NameInTypeDescription
statusquerystringComma-separated statuses to include. Defaults to all three. Example published,closed.
updatedSincequerystringISO 8601 timestamp or epoch milliseconds. Only jobs changed at or after this moment. Example 2026-09-01T00:00:00Z.
limitqueryinteger Default 50.
cursorquerystringThe nextCursor of the previous page.

Responses

200 — One page of jobs. Body: JobList.

Headers: X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset

{
  "jobs": [
    {
      "id": "job_01J8Z3K9Q0EXAMPLE",
      "status": "published",
      "title": "Senior Backend Engineer",
      "category": "engineering",
      "description": "Own the services behind our hiring pipeline, from the API surface to the queues that move applications through it.",
      "responsibilities": [
        "Design and ship services on AWS Lambda and DynamoDB",
        "Review and mentor across the backend team"
      ],
      "skills": [
        {
          "name": "TypeScript",
          "level": "required"
        },
        {
          "name": "DynamoDB",
          "level": "nice_to_have"
        }
      ],
      "benefits": [
        "Remote-first",
        "Learning budget"
      ],
      "seniority": "senior",
      "yearsExperience": "5+",
      "employmentType": "full_time",
      "contractType": "permanent",
      "salary": {
        "min": 150000,
        "max": 180000,
        "currency": "AUD",
        "period": "year"
      },
      "location": {
        "address": "Level 3, 1 Market St, Sydney NSW 2000, Australia",
        "country": "AU",
        "state": "NSW",
        "city": "Sydney",
        "remotePolicy": "hybrid",
        "onsiteDays": "2"
      },
      "workStyle": "hybrid",
      "company": {
        "name": "Acme Robotics",
        "logoUrl": "https://content.wipperoz.com/accounts/acme/logo.png"
      },
      "postedAt": "2026-09-01T02:15:00.000Z",
      "updatedAt": "2026-09-03T10:40:00.000Z",
      "expiresAt": "2026-10-01T02:15:00.000Z",
      "url": "https://www.wipperoz.com/en/jobs/acme-robotics/senior-backend-engineer",
      "applyLink": "https://www.wipperoz.com/en/apply/job_01J8Z3K9Q0EXAMPLE?src=careers&account=acc_01J8Z3EXAMPLE"
    }
  ],
  "nextCursor": null
}

400 — A query parameter is malformed. The message says which. Body: Error.

{
  "error": {
    "code": "bad_request",
    "message": "`limit` must be an integer between 1 and 100",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

401 — No API key, or one that is not valid. Body: Error.

{
  "error": {
    "code": "unauthorized",
    "message": "This endpoint requires an API key. Send it as `Authorization: Bearer <key>` or in `x-api-key`.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

403 — The key is valid but does not carry the scope this route needs. Body: Error.

{
  "error": {
    "code": "forbidden",
    "message": "This key does not carry the `jobs:read` scope. Mint a key with it in Orbit → Settings → API keys.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

429 — Over the per-key limit. Wait Retry-After seconds. Body: Error.

Headers: Retry-After

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit of 120 requests per minute exceeded. Retry after 37 seconds.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

Read one job

GET /v1/jobs/{jobId}

One of the calling account's jobs. Another account's job, a draft and an unknown id all answer 404 — a draft has no public existence yet.

Parameters

NameInTypeDescription
jobIdrequiredpathstring Example job_01J8Z3K9Q0EXAMPLE.

Responses

200 — The job.

Headers: X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset

{
  "job": {
    "id": "job_01J8Z3K9Q0EXAMPLE",
    "status": "published",
    "title": "Senior Backend Engineer",
    "category": "engineering",
    "description": "Own the services behind our hiring pipeline, from the API surface to the queues that move applications through it.",
    "responsibilities": [
      "Design and ship services on AWS Lambda and DynamoDB",
      "Review and mentor across the backend team"
    ],
    "skills": [
      {
        "name": "TypeScript",
        "level": "required"
      },
      {
        "name": "DynamoDB",
        "level": "nice_to_have"
      }
    ],
    "benefits": [
      "Remote-first",
      "Learning budget"
    ],
    "seniority": "senior",
    "yearsExperience": "5+",
    "employmentType": "full_time",
    "contractType": "permanent",
    "salary": {
      "min": 150000,
      "max": 180000,
      "currency": "AUD",
      "period": "year"
    },
    "location": {
      "address": "Level 3, 1 Market St, Sydney NSW 2000, Australia",
      "country": "AU",
      "state": "NSW",
      "city": "Sydney",
      "remotePolicy": "hybrid",
      "onsiteDays": "2"
    },
    "workStyle": "hybrid",
    "company": {
      "name": "Acme Robotics",
      "logoUrl": "https://content.wipperoz.com/accounts/acme/logo.png"
    },
    "postedAt": "2026-09-01T02:15:00.000Z",
    "updatedAt": "2026-09-03T10:40:00.000Z",
    "expiresAt": "2026-10-01T02:15:00.000Z",
    "url": "https://www.wipperoz.com/en/jobs/acme-robotics/senior-backend-engineer",
    "applyLink": "https://www.wipperoz.com/en/apply/job_01J8Z3K9Q0EXAMPLE?src=careers&account=acc_01J8Z3EXAMPLE"
  }
}

401 — No API key, or one that is not valid. Body: Error.

{
  "error": {
    "code": "unauthorized",
    "message": "This endpoint requires an API key. Send it as `Authorization: Bearer <key>` or in `x-api-key`.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

403 — The key is valid but does not carry the scope this route needs. Body: Error.

{
  "error": {
    "code": "forbidden",
    "message": "This key does not carry the `jobs:read` scope. Mint a key with it in Orbit → Settings → API keys.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

404 — No such job on this account. Body: Error.

{
  "error": {
    "code": "not_found",
    "message": "No such job on this account",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

429 — Over the per-key limit. Wait Retry-After seconds. Body: Error.

Headers: Retry-After

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit of 120 requests per minute exceeded. Retry after 37 seconds.",
    "requestId": "5f7a9c1e-2b3d-4e5f-8a9b-0c1d2e3f4a5b"
  }
}

Schemas

Error

FieldTypeDescription
errorrequiredobject

ScreeningRequest

FieldTypeDescription
templateIdrequiredstringOne of the account's active screening templates.
completeBystring (date-time)The deadline. Defaults to seven days from now.
messagestringA note the candidate reads in the invitation.
languagestringThe language of the invitation email, when the candidate is reached by email. One of: en, es, fr, pt. Default en.

ScreeningTriggered

FieldTypeDescription
screeningrequiredobject
billingrequiredstringincluded — one of the managed ad's included screenings; overage — billed at priceCents if it completes. One of: included, overage.
priceCentsrequiredintegerThe template's cost per screening, locked now, in minor units, excluding GST.
currencyrequiredstringOne of: AUD, USD.

JobList

FieldTypeDescription
jobsrequiredJob[]
nextCursorrequiredstring | nullPass back as cursor for the next page. null when there is no more.

Skill

FieldTypeDescription
namerequiredstring
levelrequiredstringOne of: required, nice_to_have.

Salary

FieldTypeDescription
minnumber
maxnumber
currencystringISO 4217, as entered by the recruiter.
periodstringFree text as entered, typically year, month, day or hour.

Location

Where the role is. address is the place in the recruiter's words — a picked suggestion's full address, or text typed by hand — and it is what the Wipperoz job page shows first. city, state and country are set only when the place was picked from a suggestion (or sent by you), so a location typed by hand is address alone: show address when it is there, and build structured data (jobLocation) from the parts. A job needs a country to be published for the first time.

FieldTypeDescription
addressstringThe place as written. At most 300 characters when you send it.
countrystringRequired to publish a job for the first time. For a remote role, the country candidates can be in.
statestring
citystring
remotePolicystringOne of: onsite, hybrid, remote.
onsiteDaysstring

Company

FieldTypeDescription
namestring
logoUrlstring (uri)

Job

Enough to build a JobPosting JSON-LD block: title, description, postedAt → datePosted, expiresAt → validThrough, company → hiringOrganization, location → jobLocation, salary → baseSalary, employmentType.

FieldTypeDescription
idrequiredstring
statusrequiredstringpublished accepts applications. The other two are returned, not omitted, so a careers page can render its own closed state. One of: published, closed, expired.
titlerequiredstring
categorystringWhat kind of job this is. Absent on a role published before categories existed. One of: engineering, data, product, design, marketing, sales, customer_success, operations, finance, hr_people, legal, healthcare, education, hospitality, retail, logistics, construction_trades, manufacturing, admin_support, other.
descriptionrequiredstring
responsibilitiesrequiredstring[]
skillsrequiredSkill[]
benefitsrequiredstring[]
senioritystring
yearsExperiencestring
employmentTypestringOne of: full_time, part_time, contract, temporary, other, volunteer, internship.
contractTypestringOne of: permanent, part_time, fixed_term, contract, casual.
salarySalary
locationLocationWhere the role is. address is the place in the recruiter's words — a picked suggestion's full address, or text typed by hand — and it is what the Wipperoz job page shows first. city, state and country are set only when the place was picked from a suggestion (or sent by you), so a location typed by hand is address alone: show address when it is there, and build structured data (jobLocation) from the parts. A job needs a country to be published for the first time.
workStylestring
companyrequiredCompany
postedAtstring (date-time)
updatedAtstring (date-time)The latest of an edit, the publish and the close. What updatedSince compares against.
expiresAtstring (date-time)The role stops accepting applications at this moment. Use as validThrough.
closedAtstring (date-time)
urlstring (uri)The Wipperoz-hosted job page, when the role has one.
applyLinkrequiredstring (uri)The hosted apply page. Link candidates here; it records that they came from your site.

JobWrite

What you may set on a job. Every field is optional on PATCH; title is required on POST. The vocabulary is the one the reads return, so an enum you already map for rendering is the enum you send. What you may **not** set: status, id, slug, url, applyLink, company, postedAt, updatedAt and closedAt are ours — derived, permanent, or a lifecycle transition with its own endpoint. Sending one is a 400, deliberately, rather than being ignored: a field you thought you set and we silently dropped is worse than an error.

FieldTypeDescription
titlestring
categorystringWhat kind of job this is, from a fixed list. Required before a role's first publish. Locked, with the title, once the ad is managed in Orbit. One of: engineering, data, product, design, marketing, sales, customer_success, operations, finance, hr_people, legal, healthcare, education, hospitality, retail, logistics, construction_trades, manufacturing, admin_support, other.
descriptionstringRich text HTML, as the Orbit editor produces. Plain text is fine.
responsibilitiesstring[]
skillsSkill[]
benefitsstring[]
senioritystring
yearsExperiencestring
employmentTypestringOne of: full_time, part_time, contract, temporary, other, volunteer, internship.
contractTypestringOne of: permanent, part_time, fixed_term, contract, casual.
salarySalary
locationLocationWhere the role is. address is the place in the recruiter's words — a picked suggestion's full address, or text typed by hand — and it is what the Wipperoz job page shows first. city, state and country are set only when the place was picked from a suggestion (or sent by you), so a location typed by hand is address alone: show address when it is there, and build structured data (jobLocation) from the parts. A job needs a country to be published for the first time.
workStylestring
expiresAtstring | null (date-time)When the role stops accepting applications. null clears it — live until closed by hand. Applies immediately, even on a published ad.
maxMatchesinteger | nullStop generating AI matches once this many exist. null removes the cap. Applies immediately, even on a published ad.

AuthoredJob

The job as its own account sees it. Identical to Job, except that status may also be draft — the state a job is created in, which the read endpoints never return. A draft already carries an applyLink. It does not resolve until the role is published; it is there so a careers page can be built against the record before it goes live.

FieldTypeDescription
idrequiredstring
statusrequiredstringOne of: draft, published, closed, expired.
titlerequiredstring
categorystringWhat kind of job this is. Absent on a role published before categories existed. One of: engineering, data, product, design, marketing, sales, customer_success, operations, finance, hr_people, legal, healthcare, education, hospitality, retail, logistics, construction_trades, manufacturing, admin_support, other.
descriptionrequiredstring
responsibilitiesrequiredstring[]
skillsrequiredSkill[]
benefitsrequiredstring[]
senioritystring
yearsExperiencestring
employmentTypestringOne of: full_time, part_time, contract, temporary, other, volunteer, internship.
contractTypestringOne of: permanent, part_time, fixed_term, contract, casual.
salarySalary
locationLocationWhere the role is. address is the place in the recruiter's words — a picked suggestion's full address, or text typed by hand — and it is what the Wipperoz job page shows first. city, state and country are set only when the place was picked from a suggestion (or sent by you), so a location typed by hand is address alone: show address when it is there, and build structured data (jobLocation) from the parts. A job needs a country to be published for the first time.
workStylestring
companyrequiredCompany
postedAtstring (date-time)
updatedAtstring (date-time)The latest of an edit, the publish and the close. What updatedSince compares against.
expiresAtstring (date-time)The role stops accepting applications at this moment. Use as validThrough.
closedAtstring (date-time)
urlstring (uri)The Wipperoz-hosted job page, when the role has one.
applyLinkrequiredstring (uri)The hosted apply page. Link candidates here; it records that they came from your site.

ConsentText

FieldTypeDescription
consentTextIdrequiredstring
versionrequiredstringSend this back in consent.version. Changes whenever the wording does.
localerequiredstringOne of: en, es, fr, pt.
textrequiredstringRender this unmodified beside your apply button.

UploadSlot

FieldTypeDescription
uploadIdrequiredstringName this in cv.uploadId within the hour.
uploadUrlrequiredstringPUT the PDF here with Content-Type: application/pdf and Content-Length equal to bytes, before expiresAt.
expiresAtrequiredstring (date-time)

ConsentReceipt

Your record of showing the candidate the consent text and recording their acceptance. Stored verbatim with the application, beside our own copy of the text in locale — what the candidate read.

FieldTypeDescription
consentTextIdrequiredstringOne of: orbit_api_apply.
versionrequiredstringThe version you rendered, from GET /v1/consent-text. Currently api_apply_v1.
localestringThe language you showed it in. The claim email goes out in it too. One of: en, es, fr, pt. Default en.
acceptedAtrequiredstring | integerWhen the candidate accepted it — ISO 8601, or epoch milliseconds. Not more than five minutes ahead of our clock.
iprequiredstringThe candidate's address at the point of acceptance.
userAgentrequiredstring

ApplicationWrite

FieldTypeDescription
namerequiredstring
emailrequiredstring (email)The candidate's own address. The claim link goes here, and one application per address per job is kept.
phonestring
locationstring
cvrequiredobject
coverNotestring
answersobject[]Your own screening questions and what the candidate answered, shown to the recruiter as typed.
consentrequiredConsentReceiptYour record of showing the candidate the consent text and recording their acceptance. Stored verbatim with the application, beside our own copy of the text in locale — what the candidate read.
lawfulBasisrequiredobject

ApplicationCreated

FieldTypeDescription
applicationIdrequiredstring
candidateIdrequiredstringThe id POST /v1/jobs/{jobId}/candidates/{candidateId}/screening takes for this person. The same value as applicationId.
statusrequiredstringOne of: received.
cvStatusrequiredstringOne of: processing.
jobrequiredobject

ApplicationStatus

FieldTypeDescription
applicationIdrequiredstring
jobIdrequiredstring
candidateIdrequiredstring
statusrequiredstringwithdrawn only when the PDF could not be read; reason says so. One of: received, withdrawn.
cvStatusrequiredstringOne of: processing, staged, claimed, deleted, failed.
createdAtrequiredstring (date-time)
claimedAtstring (date-time)Once the candidate has claimed the Virtual CV.
reasonstringOn withdrawn. One of: cv_unreadable.

CandidateWrite

FieldTypeDescription
namerequiredstring
emailrequiredstring (email)The person's own address. One import per address per account; the claim email goes here.
cvrequiredobject
sendClaimEmailbooleanWhether to email the person that a Virtual CV was built for them, with a way to claim or delete it. A person who already has an account is told either way. Default true.
localestringThe claim email's language. One of: en, es, fr, pt. Default en.
lawfulBasisrequiredobject

CandidateCreated

FieldTypeDescription
candidateIdrequiredstringThe id My candidates knows this person by.
statusrequiredstringOne of: queued, existing_account, suppressed, already_imported, rejected.
cvStatusrequiredstringprocessing only when a Virtual CV is being built (queued). One of: processing, none.
rejectionobjectOn rejected.
WipperozWipperoz

Wipperoz est une plateforme de CV virtuel interactive axée sur la vidéo, conçue pour remplacer les CV PDF traditionnels par des profils dynamiques et partageables.

© 2026 Wipperoz. Tous droits réservés

Développé par epoqx.ai