Skip to main content

Embedded Sponsorship API

Overview​

The Embedded Sponsorship API allows partners to integrate ZipRecruiter's job sponsorship capabilities directly into their ATS. Partners can generate access tokens for their users, check sponsorship status of jobs, and embed sponsorship flows in their UI.

6 Steps to Get Started​

Get a sponsorship button working in your ATS in six easy steps:

  1. Get credentials — Receive a Job API Key and a Sponsorship API Key (a single Authorization: Basic credential) from your ZipRecruiter partner contact. Also provide all domains where you will embed the SDK (including dev, staging, and production) so ZipRecruiter can whitelist them. The iframe will not load until your domains are whitelisted.
  2. Post a job — Use the Jobs API to create a job listing. A job must exist before it can be sponsored.
  3. Map user roles — Decide which roles to assign each ATS user type (e.g., admin gets can-sponsor, can-view-all-jobs, can-unsponsor, can-manage-billing; recruiter gets can-sponsor, can-view-all-jobs, can-unsponsor).
  4. Exchange credentials for an access token — Your server calls POST /ats-embed/v0/api/token with Basic Auth to get a short-lived access token.
  5. Include the SDK and annotate job elements — Add the Sponsorship SDK script tag to your ATS page with the access token, and add data-zr-job-id attributes to each job element.
  6. See the button — The SDK automatically renders a "Sponsor on ZipRecruiter" button inside each annotated element. On completion, it updates to "Pause ZipRecruiter Sponsorship."

For detailed SDK setup instructions, see the Sponsorship SDK guide.

Authentication​

The Sponsorship API uses Basic authentication to allow access to all endpoints. You will be provided an API key separate from your Jobs API key; please keep it secret.

note

If your client's Basic Auth library requires separate username and password fields, simply decode the key we provide.

Example authentication header
curl https://api.ziprecruiter.com/ats-embed/v0/api/token \
-H "Authorization: Basic YOUR_SPONSORSHIP_API_KEY" ...

Operations​

Token Exchange​

POST /ats-embed/v0/api/token

Exchange Sponsorship API credentials for an access token.

Example request
curl -X POST https://api.ziprecruiter.com/ats-embed/v0/api/token \
-H "Authorization: Basic YOUR_SPONSORSHIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "hiring@acme.com",
"externalEmployerId": "emp-456",
"atsUserId": "user-789",
"roles": ["can-sponsor", "can-view-all-jobs", "can-manage-billing"]
}'
Example response
Response
{
"access_token": "eyJhbGciOiJkaXIiLCJlbmMiOi...",
"expires_in": 7200,
"user": {
"email": "hiring@acme.com",
"state": "returning"
}
}

Request Headers​

HeaderDescription
AuthorizationBasic YOUR_SPONSORSHIP_API_KEY
Content-Typeapplication/json

Request Body​

Request body fields
FieldRequiredTypeDescription
emailYesstringUser's email address.
externalEmployerIdYesstringUnique employer identifier in your system.
facilityIdNostringOptional finer-grained identifier under externalEmployerId — see Facilities below.
atsUserIdYesstringUser's unique identifier in your ATS.
rolesNostring[]Permissions for this user (see Roles). If omitted or empty, the user has no permissions.
companyNameNostringEmployer company name (pre-fills registration).
websiteNostringCompany website URL (pre-fills registration).
zipNostringCompany zip code (pre-fills registration).
fullNameNostringUser's full name (pre-fills registration).
titleNostringUser's job title (pre-fills registration).
phoneNostringUser's phone number (pre-fills registration).

Response Body​

Response body fields
FieldRequiredTypeDescription
access_tokenYesstringBearer token (JWT) for subsequent API calls.
expires_inYesintegerToken lifetime in seconds (7200 = 2 hours).
userYesobjectUser identity and account state.
user.emailYesstringThe email address from the request.
user.stateYesstringAccount state: "returning", "new", "verify-identity", or "no-access".

Facilities​

If your externalEmployerId represents a parent account that covers multiple locations or sub-brands (for example, a franchise with several facilities), pass an optional facilityId on the token exchange request to keep each facility's billing separate.

  • Users who share the same externalEmployerId and the same facilityId (including users who never send a facilityId) end up in the same ZipRecruiter organization, with one shared payment method and plan.
  • The first facilityId seen for a given externalEmployerId establishes a new, independent ZipRecruiter organization for that facility. Every subsequent request with the same externalEmployerId + facilityId pair routes new users into that same organization.
  • Omitting facilityId is equivalent to using one fixed default facility for that employer — existing integrations that never send it see no change.
  • This affects new users only: an ATS user who already has a ZipRecruiter account continues to use their own existing organization, regardless of facilityId.

POST /ats-embed/v0/api/sponsored_status

Determine which jobs are currently sponsored.

Example request
curl -X POST "https://api.ziprecruiter.com/ats-embed/v0/api/sponsored_status" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "jobIds": ["job-010", "job-011"] }'
Example response
Response
{
"success": true,
"statuses": {
"job-010": "sponsored",
"job-011": "unsponsored"
}
}

Request Headers​

HeaderDescription
AuthorizationBearer ACCESS_TOKEN
Content-Typeapplication/json

Request Body​

FieldRequiredTypeDescription
jobIdsYesstring[]Array of external job IDs (max 50).

Embed Flow URLs​

The sponsorship widget is loaded in an iframe using the URLs below. Pass the external job ID and the access token obtained from the token exchange.

Embed flow URLs and parameters
FlowURLDescription
Sponsor/ats-embed/v0/?jobId=<id>&token=<token>Select jobs, choose distribution level, enter payment.
Manage/ats-embed/v0/manage?jobId=<id>&token=<token>View and manage sponsored jobs.
ParameterDescription
jobIdExternal job ID.
tokenAccess token from the token exchange.

Roles​

Roles control what a user can do inside the sponsorship widget. Assign roles per user when generating their access token (see the roles parameter in Token Exchange).

Available roles
RoleWhat It Controls
can-sponsorRequired to sponsor jobs. Without this role, the user sees a "no access" screen.
can-view-all-jobsWith this role, the user sees all company jobs on the job selection screen. Without it, they see only their own.
can-unsponsorRequired to stop sponsorship on a job.
can-manage-billingRequired to add or change the payment method. Without it, the user can still sponsor using an existing card on file but cannot replace it.
note

If roles is omitted or empty, the user has no permissions and cannot perform any gated actions. Roles are enforced server-side. The widget displays appropriate messages for each permission state, but the API independently rejects unauthorized requests.

Typical Role Assignments​

Typical role assignments by user type
User TypeSuggested Roles
Admin / hiring managercan-sponsor, can-view-all-jobs, can-unsponsor, can-manage-billing
Recruitercan-sponsor, can-view-all-jobs, can-unsponsor
Hiring team membercan-sponsor

Error Responses​

All Sponsorship API responses include a success boolean at the top level. On failure, success is false and an error object is included:

Example error response
{
"success": false,
"error": {
"code": "INVALID_TOKEN",
"message": "The access token is invalid or expired."
}
}
Error codes
CodeStatusDescription
UNAUTHENTICATED401Missing or invalid authorization.
INVALID_TOKEN401Bearer token is invalid or expired.
INSUFFICIENT_PERMISSIONS400User lacks a required role (see Roles).
MISSING_EMAIL400email field is missing or empty.
INVALID_EMAIL400email is not a valid email address.
MISSING_EMPLOYER_ID400externalEmployerId field is missing or empty.
INVALID_REQUEST400Request body is missing required fields or contains invalid values.
RATE_LIMITED429Too many requests; retry after the period indicated by Retry-After.
INTERNAL_ERROR500An unexpected error occurred.

Rate Limits​

All Sponsorship API endpoints are rate-limited. When a limit is exceeded the API returns HTTP 429 with a Retry-After header.

Rate limit response headers

Response Headers​

The following headers are included on every Sponsorship API response:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window.
X-RateLimit-RemainingRequests remaining in the current window.
Retry-AfterSeconds until the window resets (only on 429 responses).
Token endpoint limits

Token Endpoint Limits​

POST /ats-embed/v0/api/token is subject to two independent limits, both keyed on client_id. A request is rejected if either limit is exceeded.

ScopeLimitWindowNotes
Per client_id3,000 requests1 minuteBurst protection. Cache tokens and refresh before expiry.
Per client_id100,000 requests1 hourOverall budget across all employers for a single partner.
Sponsored status endpoint limits

POST /ats-embed/v0/api/sponsored_status is rate-limited per user.

LimitWindow
60 requests1 minute