Creating a job publishes it. An ONLINE job is posted to job boards; an OFFLINE job stays internal. Both count toward the active-job limit and must pass publish validation. The examples below explicitly use OFFLINE, which still creates a real job if executed.
1. Choose supporting values
Use the subsections under Jobs:
- Contract types: select a country-specific contract type for an on-site or hybrid role, or a generic type for a remote role. Read its employment-term bounds.
- Employment types: interpret returned employment types or choose a job filter. Employment type follows from the contract type.
- Pipeline templates: optionally choose the template for the new job’s stages.
- Remote regions: choose the region for a region-based remote role.
For an on-site or hybrid job, read Locations and choose a location ID. All IDs in examples are fictional: replace them with values returned for your company. The remote example’s contract type 13 represents a generic type returned when countryCode is omitted.
2. Create the job
curl --fail-with-body "https://api.join.com/v3/jobs" \
-H "Authorization: Bearer $JOIN_API_TOKEN" \
-H "Join-Version: 2026-11-01" \
-X POST \
-H "Content-Type: application/json" \
--data '{
"title": "Backend Engineer",
"description": "<p>Help our engineering team build and maintain recruiting software. You will design reliable services, review code with colleagues, investigate production issues and improve the experience of our customers. We value clear communication, thoughtful testing and practical problem solving.</p>",
"languageCode": "en",
"status": "OFFLINE",
"workLocation": {
"workplaceType": "ONSITE",
"locationId": 1234
},
"contractTypeId": 12,
"pipelineTemplateId": 77,
"externalId": "ATS-4711"
}'The description contains more than 200 visible characters; HTML markup does not count toward that requirement. See Create a job for all fields and a complete remote-job example.
Save data.id from the response. Read the job’s returned stages to find the stage IDs for moving applications.
3. Update the job
Read Get a job before assembling an update. Omit unchanged fields. Work location, compensation, application form and hiring-team values replace their previous values when supplied; employment terms have separate field-level rules. null is supported only on documented nullable fields.
For example, replace an existing workplace configuration with remote-anywhere and a compatible generic contract type:
curl --fail-with-body "https://api.join.com/v3/jobs/4321" \
-H "Authorization: Bearer $JOIN_API_TOKEN" \
-H "Join-Version: 2026-11-01" \
-X PATCH \
-H "Content-Type: application/json" \
--data '{
"workLocation": {
"workplaceType": "REMOTE",
"remoteType": "ANYWHERE"
},
"contractTypeId": 13
}'Job fields, hiring-team assignments and status are saved together. Custom screening questions are updated separately and can remain changed if a later step fails. Read the job and its application form after a failure before retrying. If updates overlap, the last write determines the stored values.
To change status, use Update a job with the intended status. Review the endpoint’s business-rule errors before automating publication or archival.