Migrate one operation at a time. A /v2 to /v3 string replacement is not sufficient: paths, fields, response envelopes and available operations differ. This guide maps v2 operations to revision 2026-11-01; confirm access to that revision before switching production traffic.
Prepare the client
- Verify a company token with a read-only v3 request. Migrated credentials and new company tokens may be used during transition; check your company’s current access instead of assuming every historical key is still valid.
- Pin
Join-Version: 2026-11-01on v3 requests. - Read successful JSON under
data. Handle204without parsing a body. Replace page-number assumptions with cursor handling only on endpoints that paginate. - Branch on
error.codeand inspect field-leveldetails, includingfield,inandmessage. - Re-resolve candidate IDs through v3 responses; do not assume a historical global candidate ID equals the company candidate ID.
- Compare results in an authorized test environment and switch each supported operation separately. Avoid dual-running writes against shared data.
Endpoint mapping
Paths below omit the /v2 or /v3 prefix. Similar paths do not imply identical payloads.
| v2 operation | v3 equivalent or action |
|---|---|
GET /jobs, GET /jobs/{id} | Same paths; new response schema under data |
POST /jobs, PATCH /jobs/{id} | Same paths; use the v3 job input, including workLocation and contractTypeId |
PATCH /jobs/{id}/changeStatus, /activate, /archive | PATCH /jobs/{id} with status; check status-specific validation |
GET /applications, GET /applications/{id}, POST /applications | Same paths; new application and candidate shapes |
PATCH /applications/{id}/externalData | PATCH /applications/{id} with externalId only |
GET /applications/{id}/scorecards | GET /scorecards?candidateId=...; candidate-wide results, not equivalent application-only filtering |
GET /candidates, GET /candidates/{id} | Same paths; use company candidate IDs |
GET, POST /candidates/{id}/notes | Same route shape; path parameter is named candidateId in the reference |
DELETE /candidates/{id}/notes/{noteId} | Same route shape; deletes the note and related replies and reactions |
GET, POST /offices; GET, PATCH /offices/{id} | Corresponding operations under /locations; field and error-code terminology changes to location |
GET /employmentTypes | GET /employment-types; use slugs for job filtering |
Operations without a direct v3 equivalent
| v2 operation | Current v3 boundary |
|---|---|
DELETE /applications/{id} | No application-delete endpoint; manage the application in JOIN. Candidate deletion removes much more data |
PUT /applications/{id}/tags | No general application-tag update endpoint |
PATCH /candidates/{id} | No candidate-profile update endpoint |
PATCH /candidates/{id}/notes/{noteId} | Notes are immutable after creation |
GET /categories, GET /seniorityLevels | No corresponding lookup endpoints |
GET /attachments/{id}/{externalFileName}, GET /application-files/{id}/{externalFileName} | Read temporary download URLs from the v3 application response; re-read for fresh links |
Behavior to check explicitly
- Applications use
status(ACTIVE,REJECTED,HIRED) andcurrentStage;OFFERis not a status. - Read job stages from
GET /jobs/{id}and move viaPUT /applications/{id}/stagewithstageId. - Job employment type follows from contract type, and draft jobs are not returned.
- Review the scope of candidate deletion: it permanently removes the candidate and all their applications, notes and attachments.
externalIdon jobs is not unique and is not an idempotency key.- Use the
Accept-Languageheader to translate supported display names andlanguageCodeto select the ad’s language. See Languages and localized values for language selection and fallback.
Consult the reference for every payload conversion and Responses, errors and retries for uncertain write outcomes. Use JOIN release communications and deprecation notices to schedule the migration.