Moving from v2 to v3

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

  1. 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.
  2. Pin Join-Version: 2026-11-01 on v3 requests.
  3. Read successful JSON under data. Handle 204 without parsing a body. Replace page-number assumptions with cursor handling only on endpoints that paginate.
  4. Branch on error.code and inspect field-level details, including field, in and message.
  5. Re-resolve candidate IDs through v3 responses; do not assume a historical global candidate ID equals the company candidate ID.
  6. 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 operationv3 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, /archivePATCH /jobs/{id} with status; check status-specific validation
GET /applications, GET /applications/{id}, POST /applicationsSame paths; new application and candidate shapes
PATCH /applications/{id}/externalDataPATCH /applications/{id} with externalId only
GET /applications/{id}/scorecardsGET /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}/notesSame 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 /employmentTypesGET /employment-types; use slugs for job filtering

Operations without a direct v3 equivalent

v2 operationCurrent v3 boundary
DELETE /applications/{id}No application-delete endpoint; manage the application in JOIN. Candidate deletion removes much more data
PUT /applications/{id}/tagsNo 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 /seniorityLevelsNo 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) and currentStage; OFFER is not a status.
  • Read job stages from GET /jobs/{id} and move via PUT /applications/{id}/stage with stageId.
  • 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.
  • externalId on jobs is not unique and is not an idempotency key.
  • Use the Accept-Language header to translate supported display names and languageCode to 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.