Jobs API
Overview
The Jobs API allows ZipRecruiter partners to create, update, retrieve, and close job listings on our network.
One endpoint, https://api.ziprecruiter.com/partner/v0/job supports basic CRUD operations.
Authentication
This API uses Basic authentication. Include your API key in the Authorization header of every request.
The Job Model
The job is represented as a JSON object in the request or response body. Fields are optional unless otherwise specified.
Do not include fields that have no value when you create a new job (POST).
In an update (PUT), some fields can be erased by sending a JSON null value
(for example, apply_url). Not every field is nullable, however — see the
Compensation notes below for the rules that apply to
compensation fields.
Required Fields
Required fields reference
| Field | Required | Type | Description |
|---|---|---|---|
job_id | Yes | string | Unique job ID in the partner's system. 1–100 characters. |
employer_id | Yes | string | Unique employer ID in the partner's system. |
employer_name | Yes | string | Employer display name. Required on the first job for a given employer; optional after that. |
title | Yes | string | Job title. |
job_type | Yes | enum | One of: full_time, part_time, contractor, contract, temporary, other. |
country | Yes | enum | One of: US, CA, AU. |
description | Yes | string | Job description, minimum 25 characters. May include these HTML tags: p em i strong b br ol ul li hr div. |
employer_id determines which jobs are pooled together for sponsorship —
it does not determine billing. If you use the Sponsorship
API's optional facilityId to split one employer_id
into separate billing organizations, every one of those organizations can
still see and sponsor any job posted under that employer_id. See
Facilities.
Location Fields
A job location is required. You must always provide country, and then either:
postal_code, orcityandstate, orlatitudeandlongitude
If you have more than one of the above, provide all that you have. For remote jobs, you can give the location of the hiring company's headquarters.
For the most reliable resolution, send city, state, and country together.
Submitting only a partial location (for example, state and postal_code without
city) may fail to resolve and be rejected.
Location fields reference
| Field | Required | Type | Description |
|---|---|---|---|
city | Conditional | string | City name. |
state | Conditional | string | Two- or three-letter ISO 3166-2 abbreviation (including Canada and Australia). |
postal_code | Conditional | string | Postal/ZIP code. |
latitude | Conditional | number | Latitude, e.g. 40.71427. |
longitude | Conditional | number | Longitude, e.g. -74.00597. |
For Australian provinces, the API supports both two- and three-letter codes. However, the ZipRecruiter website currently only displays the two-letter codes.
Optional Fields
Optional fields
| Field | Required | Type | Description |
|---|---|---|---|
compensation_min | No | number | Minimum compensation (positive, fixed point or integer). |
compensation_max | No | number | Maximum compensation (positive, fixed point or integer). |
compensation_period | No | enum | One of: annual, monthly, weekly, daily, hourly. |
compensation_currency | No | enum | One of: USD, CAD, AUD. |
show_compensation | No | boolean | Whether salary range should be shown with the job listing. Defaults to true when compensation_min or compensation_max is provided. Set to false to include compensation data without displaying it publicly. |
apply_url | No | string | URL for external apply, or for automated delivery with some ATS. |
accept_remote | No | boolean | Whether the job can be performed remotely. Acceptable values: true, false, 1, 0. |
requisition_id | No | string | Unique requisition ID, used during candidate application delivery. 1–100 characters. |
ats_user_id | No | string | Identifier for the user who posted the job in your ATS. Maximum 100 characters. Returned in GET responses when present. |
cpc | No | number | Cost per click, optionally with decimal fractions, e.g. 12.49. |
partner_attributes | No | object | Key-value pairs where keys are strings, containing any partner-specific attributes. |
employer_logo_base64 | No | string | Base64-encoded employer logo (PNG, JPEG, or GIF). Length 500-360000 base64 characters (~375 B to ~270 KB raw image). When provided, sets the employer's logo (replacing any previous one). |
benefits_perks | No | object | Benefits offered with the job. Keys: medical, dental, vision, 401k, life_insurance, pension; each value is 1 (offered) or 0 (not offered). When provided, must contain at least one key. Returned in GET responses when present. |
Compensation Fields
Compensation behaves differently from other fields on update (PUT). Note the following rules:
compensation_minandcompensation_maxmust be positive. Sending0for either value is rejected.- To erase compensation on an update, send
nullfor bothcompensation_minandcompensation_max. Erasing the compensation range also clears the storedshow_compensationsetting. compensation_currencyandcompensation_periodcannot be set tonull. When present they must be one of the enumerated values; sendingnullis rejected. To stop sending compensation, erase the range as described above rather than nulling the currency or period.- Omitting compensation fields on a PUT does not erase them. Any previously stored compensation values are preserved.
show_compensationonly takes effect when compensation values are present. Sendingshow_compensation: falseon its own — with nocompensation_minorcompensation_max— has no effect on a job that has no stored compensation.
Examples
Minimal job example
{
"employer_id": "emlwcGFydG5lcg-042",
"employer_name": "Stenographica, Ltd",
"job_id": "emlwcmVjcnVpdGVy-3215",
"title": "Longhand",
"job_type": "contract",
"state": "NY",
"city": "New York",
"country": "US",
"description": "<div>We need someone to write things by hand, on paper, legibly, in cursive.</div>"
}
Full job example with all optional fields
{
"employer_id": "emlwcGFydG5lcg-042",
"employer_name": "Stenographica, Ltd",
"job_id": "emlwcmVjcnVpdGVy-3215",
"title": "Senior Calligrapher",
"job_type": "full_time",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "US",
"latitude": 40.71427,
"longitude": -74.00597,
"description": "<div><p>We are seeking a Senior Calligrapher with 5+ years of experience in hand-lettering and manuscript preparation.</p><ul><li>Expert in cursive and italic scripts</li><li>Experience with archival-quality inks</li></ul></div>",
"compensation_min": 55000,
"compensation_max": 75000,
"compensation_period": "annual",
"compensation_currency": "USD",
"show_compensation": true,
"apply_url": "https://careers.stenographica.example.com/apply/3215",
"accept_remote": false,
"requisition_id": "REQ-2024-3215",
"ats_user_id": "user-789",
"cpc": 1.50,
"employer_logo_base64": "iVBORw0KGgoAAAANSUhEUgAA...AAAASUVORK5CYII=",
"benefits_perks": {
"medical": 1,
"dental": 1,
"vision": 1,
"401k": 1,
"life_insurance": 0,
"pension": 0
},
"partner_attributes": {
"department": "Creative Services",
"experience_level": "senior"
}
}
Operations
Unicode in job_ids
In the Jobs API's GET, PUT, and DELETE operations, a job_id is included in the URI.
If this job_id has any characters that are not in the unreserved set, they must be UTF-8
encoded, then the bytes URL-encoded (percent-encoded)
Wikipedia.
(curl does this automatically, perhaps your library of choice does as well.)
Create a Job
Creates a new job. The job (identified by job_id) cannot already exist.
The body must contain a JSON object matching the job model.
POST https://api.ziprecruiter.com/partner/v0/job
Example request
curl https://api.ziprecruiter.com/partner/v0/job \
-H "Authorization: Basic YOUR_API_KEY" \
-X POST \
-H "Content-Type: application/json" \
-d @job.json
Example response
{
"job": {
"job_id": "emlwcmVjcnVpdGVy-3215",
"title": "Longhand",
"job_type": "full_time",
"latitude": "40.71427000",
"longitude": "-74.00597000",
"city": "New York",
"state": "NY",
"country": "US",
"employer_id": "emlwcGFydG5lcg-042",
"employer_name": "Stenographica, Ltd",
"description": "<div>We need someone to write things by hand, on paper, legibly, in cursive.</div>",
"preview_url": "https://www.ziprecruiter.com/job/a1b2c3d4"
},
"success": true
}
Update a Job
Updates an existing job. The job (identified by its job_id in the body) must already exist.
Updating a job always makes it active again, even if it was previously closed. If you only want to modify fields without reactivating, be aware of this behavior.
Either:
PUT https://api.ziprecruiter.com/partner/v0/jobPUT https://api.ziprecruiter.com/partner/v0/job/<JOB_ID>
If the latter URL is used, the JOB_ID in the URL must match the one in the body.
Example request
curl https://api.ziprecruiter.com/partner/v0/job \
-H "Authorization: Basic YOUR_API_KEY" \
-X PUT \
-H "Content-Type: application/json" \
-d @job.json
Example response
{
"job": {
"job_id": "emlwcmVjcnVpdGVy-3215",
"title": "Longhand (Updated)",
"job_type": "full_time",
"city": "New York",
"state": "NY",
"country": "US",
"employer_id": "emlwcGFydG5lcg-042",
"employer_name": "Stenographica, Ltd",
"description": "<div>Updated description.</div>",
"preview_url": "https://www.ziprecruiter.com/job/a1b2c3d4"
},
"success": true
}
Get a Job
Retrieves a specific job by ID. The response includes a job_status field indicating the
current state of the job. The job object includes a preview_url field pointing at the
public job posting.
GET https://api.ziprecruiter.com/partner/v0/job/<JOB_ID>
| Parameter | Description |
|---|---|
JOB_ID | The ID of the job to retrieve. |
If your job_id has UTF-8, it must be properly encoded for the URI. See the note above.
Example request
curl "https://api.ziprecruiter.com/partner/v0/job/emlwcmVjcnVpdGVy-3215" \
-H "Authorization: Basic YOUR_API_KEY"
Example response
{
"job": {
"job_id": "emlwcmVjcnVpdGVy-3215",
"title": "Longhand",
"job_type": "full_time",
"latitude": "40.71427000",
"longitude": "-74.00597000",
"city": "New York",
"state": "NY",
"country": "US",
"employer_id": "emlwcGFydG5lcg-042",
"employer_name": "Stenographica, Ltd",
"description": "<div>We need someone to write things by hand, on paper, legibly, in cursive.</div>",
"preview_url": "https://www.ziprecruiter.com/job/a1b2c3d4"
},
"job_status": "posted",
"success": true
}
The job_status field can be one of:
Job status values
| Status | Meaning |
|---|---|
posted | The job is posted and live. |
pending | The job is yet to be posted. |
deleted | The job is closed and removed from our search engine. |
Close a Job
Closes (deletes) a specific job, removing it from the search engine.
DELETE https://api.ziprecruiter.com/partner/v0/job/<JOB_ID>
| Parameter | Description |
|---|---|
JOB_ID | The ID of the job to close. |
If your job_id has UTF-8, it must be properly encoded for the URI. See the note above.
Example request
curl "https://api.ziprecruiter.com/partner/v0/job/emlwcmVjcnVpdGVy-3215" \
-H "Authorization: Basic YOUR_API_KEY" \
-X DELETE
Example response
{
"job": {
"job_id": "emlwcmVjcnVpdGVy-3215"
},
"success": true
}
Re-open a Job
To re-open a job, simply update it again. (It is fine to PUT with exactly the same fields.)
Error Responses
Most errors from the Jobs API return HTTP status 400 with a JSON body describing the problem:
Example error response
{
"error": "Invalid Payload: Property is required: /job_id.",
"success": false
}
Error scenarios
| Status | Scenario | Example Error |
|---|---|---|
| 400 | Missing required field | "Property is required: /job_id." |
| 400 | Invalid enum value | "Value is not one of the enumerated values: /job_type." |
| 400 | Unsupported location | "The job location you provided is not supported. Please reference this link for supported locations: https://tools.usps.com/zip-code-lookup.htm?citybyzipcode" |
| 400 | Job already exists (POST) | "Record already exists." |
| 400 | Job not found (PUT/DELETE) | "Record not found." |
| 401 | Invalid or missing API key | Unauthorized |
| 404 | Job not found (GET) | "Record not found." |
| 500 | Internal Server Error | Try again later. |
| 503 | Service Unavailable | Temporarily offline for maintenance. |