Campaign Management API
Overview
The ZipRecruiter Campaign Management API allows you to automate and streamline how you create, manage, and retrieve information about your ZipRecruiter campaigns. With this API, you can access campaign details, create and update campaigns, adjust budgets and CPA targets, and make real-time changes to feeds, segments, and campaign goals directly from your platform.
This API is recommended for programmatic partners with the ability to build and maintain a custom integration within their platforms. ZipRecruiter provides the API endpoints and access, while partners are responsible for developing, hosting, and maintaining the integration logic and workflows used to create, manage, and update campaigns and budgets in alignment with ZipRecruiter's API specifications and usage requirements.
Benefits of using the Campaign Management API include:
- 1-1 alignment of campaigns in your systems and the ZipRecruiter platform.
- Ability to segment jobs more extensively. Segmented campaigns perform independently instead of collectively, and ZipRecruiter CSMs and algorithms optimize at the campaign level.
- Instant campaign edits.
- Faster time to value for all campaign implementations.
- Ability to dynamically update target CPAs, budgets, and campaign objectives for optimal conversion performance.
Getting Started
API Access & Authentication
All partners must be configured as a Data Sharing Partner (DSP) as a requisite to using the ZipRecruiter Campaign Management API. DSP configuration is required to enable delivery of click and/or conversion files as part of the integration.
If you are already configured as a DSP within the ZipRecruiter Marketplace—or if you leverage one of ZipRecruiter's supported DSPs—no additional action is required. See Click & Conversion Data Delivery for new DSP setup.
Once the DSP setup is complete, ZipRecruiter will generate a unique API key tied to your organization within the ZipRecruiter Marketplace. API keys are distributed via a secure, one-time link that remains accessible for up to one week.
API Scope & Permissions
The API key provides access to campaign and budget management functionality and allows you to manage only campaigns created through the API. Campaigns created outside of the API cannot be modified via API.
If you have customers billing in multiple currencies, additional ZipRecruiter Marketplace organizations—and corresponding API credentials—may be required, as only one API key can be issued per Marketplace org.
This API supports campaign and budget management only. Account creation is not supported via the API.
Testing & Validation
While ZipRecruiter does not offer a dedicated sandbox testing environment, we will provide a designated test account ID and guidance to help you validate your integration using our dynamic platform. All testing activity is performed against production systems and must be limited to the provided test account ID. See Testing Requirements.
Marketplace Account Setup
New Account creation will still need to be handled internally by ZipRecruiter. As part of the implementation process, ZipRecruiter will work with partners to assess account setup needs and define a standardized process to support ongoing Marketplace account creation.
Marketplace Campaign Visibility & User Access
The API key provides access to all campaigns associated with your ZipRecruiter Marketplace organization. However, campaign visibility within the Marketplace UI is permission-based.
Users must be explicitly added to the organization in order to view and manage campaigns in the Marketplace dashboard. There is no limit to the number of users that can be associated with an organization, but user access is currently managed by ZipRecruiter. Contact your ZipRecruiter support team to request access updates or to add users to your Marketplace dashboard.
How It Works
Authentication
The ZipRecruiter Campaign Management API is a REST-ful API with all requests and responses sent over HTTPS and authenticated by HTTP Basic Authentication.
All API responses are returned with HTTP response codes used to denote success (2xx), client-caused failure (4xx), and server-caused failure (5xx). Responses can be formatted as JSON.
Test Environment (Swagger UI)
ZipRecruiter provides access to a dynamic testing interface, accessible via Swagger UI, for API exploration, integration testing, and validation. All requests are executed against production systems and should be performed using the test account ID provided during implementation. This interface is only intended to support manual testing and validation during development.
This environment is not designed for automated testing workflows or for creating, managing, or modifying live campaigns, budgets, or production activity within the ZipRecruiter Marketplace.
Job Ingestion
The Campaign Management API supports job ingestion via an HTTPS- or FTP-hosted XML feed URL. FTP feeds must be provided in RFC 1738 format:
ftp://user:password@ftp.ziprecruiter.com/feeds/example-feed.xml
Alternatively, jobs can be created and closed programmatically using the ZipRecruiter Job API. Details on both ingestion methods are covered in Managing Jobs. To enable Job API access or determine which ingestion method best fits your integration, contact your ZipRecruiter support team.
Endpoints
Base URL: https://api.ziprecruiter.com/campaign-manager/v1
The API supports GET, POST, and PUT requests, with 1 object per call. Batch operations are not currently supported. All data should be sent with Content-Type: application/json.
| Method | Path | Description |
|---|---|---|
| GET | /ping | Demonstrate API server is responding |
| GET | /accounts | Retrieve a list of accounts |
| GET | /account/{accountId} | Retrieve an account by id |
| GET | /account/{accountId}/campaigns | Retrieve a list of campaigns |
| POST | /account/{accountId}/campaign | Create a campaign |
| GET | /account/{accountId}/campaign/{campaignId} | Retrieve a campaign by id |
| PUT | /account/{accountId}/campaign/{campaignId} | Update a campaign by id |
| GET | /account/{accountId}/campaign/{campaignId}/budget | Retrieve the current active budget for this campaign |
| POST | /account/{accountId}/campaign/{campaignId}/budget | Create a budget for a campaign |
| GET | /account/{accountId}/campaign/{campaignId}/budgets | Retrieve a list of current and future budgets for this campaign |
| GET | /account/{accountId}/campaign/{campaignId}/budget/{budgetId} | Retrieve a budget by id |
| PUT | /account/{accountId}/campaign/{campaignId}/budget/{budgetId} | Update a budget by id |
Field-by-field request and response schemas live in the API Reference.
Budget configuration is supported only at the campaign level; account-level budgets are not currently available. All spend limits must be managed at the individual campaign level.
Rate Limiting
The API supports up to 5 simultaneous requests per second per API key. Additional requests are queued, with a maximum queue depth of 10 requests.
If all processing slots are occupied, queued requests will wait for one of the five available slots to open. Depending on request size and processing time, queued requests may time out. If the queue exceeds the 10-request limit, the API will return an HTTP 503 Service Temporarily Unavailable error response.
Rate limiting is bound to the authorization request (issued unique API key). Only 1 API key can be generated per Marketplace organization.
Request Timeouts
API requests will time out after 120 seconds (2 minutes). If a request exceeds this limit, the API will return an HTTP 504 Gateway error response, indicating that the request did not complete within the allowed timeframe. Partners should ensure requests are optimized to complete within this timeframe.
Request Paths & Identifiers
Resources such as accounts, campaigns, and budgets are referenced using unique identifiers:
accountId: the Marketplace account identifier used to create and manage campaigns. Request it directly from your ZipRecruiter account representative, or retrieve it viaGET /accountsorGET /account/{accountId}.campaignId: the campaign identifier returned when a campaign is created (required for campaign updates and budget management).budgetId: the budget identifier returned when a budget is created (required for budget management).
Field Reference
Every object's fields — types, required/read-only flags, and usage notes (character limits, defaulting behavior, apply-type support) — are documented per endpoint in the API Reference, generated directly from the API's OpenAPI spec. The same descriptions appear in the Swagger UI.
Request Sequencing
Setting a campaign live requires multiple API requests executed in a specific sequence. Requests must be executed sequentially, as later steps depend on the successful completion of prior actions. Campaigns cannot be activated without a budget record.
New campaigns (three calls, in order):
POSTrequest to create the campaign (created in aPausedstatus)POSTrequest to create the campaign budgetPUTrequest to update the campaign status toActive
Existing campaigns (two calls, in order):
POSTrequest to create a new budget (orPUTto update an existing one)PUTrequest to update the campaign status toActive
Full request examples are in Integration Workflows.
Campaign Statuses
The API supports the following campaign statuses:
Active— the campaign is live and eligible to spend when budget and jobs are available.PausedandCancelled— the campaign is not active and will not spend.
Auto-Disabled Campaigns
Campaigns may also enter an Auto-Disabled status, indicating the campaign has been automatically turned off by ZipRecruiter systems.
A campaign will transition to Auto-Disabled if it remains in an Active status for more than two days after the associated budget flight has ended and no future budget is available. During routine system checks (roughly every 24 hours), ZipRecruiter evaluates active campaigns for available budget; if none is detected, the campaign is automatically disabled.
Auto-Disabled is functionally equivalent to a campaign being paused: the campaign is "off" and will not spend. This status is system-applied and cannot be set via API.
Campaigns in Paused, Cancelled, or Auto-Disabled statuses must be explicitly reactivated via the API in order to resume delivery. When a new budget is created for a campaign that is Auto-Disabled, a separate status update request is required to transition the campaign back to Active. Partners should account for scenarios where a campaign may require reactivation, including cases where it has been automatically disabled by the system.
Integration Workflows
Account Creation
The Campaign Management API does not presently support account creation. Marketplace accounts must be provisioned internally by ZipRecruiter before API campaigns can be created.
Accounts are set up on a one-account-per-employer basis. Each account is created and configured in the ZipRecruiter Marketplace for the appropriate campaign delivery type (External Apply or ZipApply). Campaign creation is permitted only after the account setup has been completed and confirmed by ZipRecruiter.
Account organization when supporting both apply types for a single employer:
- ZipApply campaigns require additional account-level configuration and a separate test account. Multiple Marketplace accounts for the same employer are required only when both apply types are used (External Apply and ZipApply).
- ZipApply and External Apply campaigns cannot coexist within the same account, as ZipApply integrations require account-level configuration that is not compatible with External Apply campaigns.
New Campaign Workflow
Creating and activating a new campaign requires three distinct calls, performed in order. Campaigns must be created in a Paused status, and a campaign must have a budget before it can be set to Active — attempting to activate without a budget returns a 4XX Bad Request error.
Step 1: Create Campaign (Paused)
Key parameters:
name— the campaign name (max 255 characters); must be unique within the account. Duplicate names return a 400 Bad Request error.country— a single ISO 3166-1 alpha-2 country code representing where jobs are located (e.g.,US,CA,GB,DE). Only one country per campaign is supported. If a job's country code does not match the campaign's country, the job will be rejected.status— all new campaigns must be created with a status ofPaused.currency(optional) — currency for bid and budget values. Must match the Marketplace organization's currency. If omitted, defaults to the org currency; if provided and mismatched, no error is returned and the org currency is used.feed_url— the job feed URL containing job data for the campaign. Required for all External Apply campaigns where jobs are sourced from a client-provided XML feed. Not required for accounts where a ZipApply feed has been pre-configured. See Managing Jobs.target_cpa— the campaign's target CPA goal. Optional unless the campaign uses Performance Optimizer withcampaign_objectiveset tocost_per_apply, in which case it is required. See Campaign Objectives.
Example POST request:
{
"name": "Best Test Co. - High Priority",
"country": "US",
"status": "Paused",
"currency": "USD",
"feed_url": "https://www.ziprecruiter.com/feed/example-feed.xml"
}
The campaign_id returned in the response is required for all subsequent campaign-level actions.
Step 2: Create Budget
Budget creation defines the campaign flight by specifying both the spend amount and the timeframe in which those funds are applied. Each budget corresponds to a single flight period. Key parameters:
start_date— ISO 8601 date for when this budget becomes active. Required for the initialPOST; all subsequentPUTcalls must include the exact same value. Budgets begin at 00:00:00 America/Los_Angeles time. Must be the current date or in the future, and cannot be changed after the budget has started.end_date— ISO 8601 date for when this budget ends. Required on the initialPOST; may be omitted on subsequentPUTcalls. Budgets end at 23:59:59 America/Los_Angeles time. Must be in the future and after thestart_date.currency(optional) — same behavior as on campaigns: defaults to the org currency; a mismatched value is ignored without error.total_budget— total amount of money available to spend in the budget flight. Must be at least 25.00 regardless of currency. Zero is not valid and triggers an error. Required whenbudget_cap_typeisFixed; must NOT be provided whenbudget_cap_typeisOpen(a 4XX error is returned).bid(optional) — the campaign starting bid. Whenzip_managed_bidsistrue, the bid value is ignored and the starting bid is set by ZipRecruiter. Whenfalse, bids below the minimum CPC are adjusted upward with a warning. The minimum CPC varies by campaign country and account type: for GB, DE, and IE campaigns the minimum depends on whether the account is Job Board or Enterprise (Agency/Staffing/Direct); for all other countries, values below 0.61 are overridden to 0.61. If omitted or null, the bid defaults to the applicable minimum.budget_cap_type(optional) —fixed,open, ornull(values are lowercase). Defaults tofixedwhen omitted or null. See Managing Budgets.
Example POST request:
{
"start_date": "2026-01-01",
"end_date": "2026-01-31",
"currency": "USD",
"total_budget": 10000,
"bid": 3.5,
"budget_cap_type": "fixed"
}
Step 3: Activate Campaign
The campaign PUT request should include the same required parameters as the create request:
name— may be updated, provided it remains unique within the account. Updates are applied based oncampaign_id, not the campaign name.country— cannot be changed after campaign creation.status— since the campaign now has a budget, set toActive.feed_url— may be updated to change the campaign's job feed source.
Example PUT request:
{
"name": "Best Test Co. - High Priority",
"country": "US",
"status": "Active",
"feed_url": "https://www.ziprecruiter.com/feed/example-feed.xml"
}
Budget notes:
- Once a campaign is
Active, additional future budget records can be created to extend flight durations without creating a new campaign. - Budgets should be renewed monthly under the existing campaign.
- Budget
start_dateandend_datecannot be the same;end_datemust come afterstart_date.
Existing Campaign Workflow
Reactivating an existing campaign requires two calls: create a budget (Step 2 above), then update the campaign status to Active (Step 3 above). Campaigns in Paused, Cancelled, or Auto-Disabled states should be treated the same — the campaign is inactive and must be reactivated via API after a budget is in place.
Deactivating Existing Campaigns
For API-managed campaigns, pausing a campaign only stops ad spend — it does not immediately remove jobs from ZipRecruiter.
To stop traffic delivery while ensuring jobs are removed as quickly as possible:
- Remove the applicable jobs from your XML feed.
- Pause or deactivate the campaign via the Campaign API.
Removing jobs from the feed first allows ZipRecruiter to begin closing those job postings immediately, preventing job seekers from being directed to expired or unavailable positions (for example, from job alert emails).
If a campaign is paused before the jobs are removed from the XML feed, campaign spend stops immediately, but the associated jobs may remain live on ZipRecruiter for a short period before being removed. This behavior is intentional and avoids broken links or directing candidates to jobs that are no longer accepting applications.
Campaign Filtering
Campaign filtering determines which jobs from an XML feed are included in a campaign. Two approaches are supported:
Option 1: Dedicated campaign feed. Provide an XML feed that contains only the jobs you want sponsored for the campaign. No filter rules are required.
Option 2: Shared feed with filter rules. Provide a general XML feed containing multiple jobs, then use campaign filter rules to include or exclude the jobs that belong to a specific campaign. Recommended when multiple campaigns share the same XML feed. Avoid filtering on fields such as job title or requisition ID unless the values are static and guaranteed to remain unique — we strongly recommend a unique campaign_id field to identify jobs for a campaign. If the value of a filtered field changes in the XML feed, the job will no longer match the filter and will be removed from the campaign.
Filter Rules
The field and value must match what's actually present in the feed XML, and the filtered field needs to remain static. Changes to the feed format can cause a disruption of service.
| Field | Required | Description |
|---|---|---|
rule | ✅ | The filter operator. Supported values: include or exclude. |
field | ✅ | The XML feed field to filter on. Any job node in the XML feed may be used. Field names must exactly match the XML feed specification. |
value | ✅ | The value to match against the selected field. Matching is case-sensitive and includes all whitespace (including leading and trailing). Values cannot contain double quotes (") or comma-space (, ). |
Filter Logic
- The only supported operators are
includeandexclude. - There is no limit to the number of filter rules per campaign.
- Multiple rules on the same field use OR logic.
- Rules across different fields use AND logic: the system looks for jobs that match all conditions, and a job missing one of the rules is rejected.
For example, the rules include company = ABC, include company = XYZ, include campaign_id = west_region evaluate as (company = ABC OR company = XYZ) AND (campaign_id = west_region).
To remove all filter rules from a campaign, update the campaign with an empty array: "feed_filters": [].
Partner Attributes
The partner_attributes field is used to reference custom or unsupported XML feed fields that fall outside of ZipRecruiter's standard feed specification:
| Campaign Type | Behavior |
|---|---|
| ZipApply | partner_attributes are automatically appended to custom fields used in filter rules. Including this field in the API request body is optional. |
| External Apply | partner_attributes are not automatically appended. Include this field when filtering on custom or unsupported feed fields; otherwise those fields are not recognized during filtering and matching jobs may be excluded from the campaign. |
Filtering on Custom Fields
Custom or unsupported feed fields must always be nested under partner_attributes in the XML feed. For External Apply campaigns, partner_attributes must also be included in the API request so the system can recognize and evaluate those fields during filtering.
XML feed:
<partner_attributes>
<campaign_id>12345</campaign_id>
<region>West</region>
</partner_attributes>
Filter rule:
{
"field": "campaign_id",
"rule": "include",
"value": "12345"
}
Managing Budgets
Campaign budgets are managed as time-bound budget records. Each budget represents a window of time defined by a start_date and end_date, and can be configured as:
- Fixed (
budget_cap_type = "fixed") — a budget with a defined spending cap. - Open (
budget_cap_type = "open") — a budget without a fixed spending cap. - Null — defaults to fixed to preserve backwards compatibility with existing integrations.
budget_cap_type values are lowercase and case-sensitive: Fixed or Open are rejected with invalid_budget_cap_type.
Budget Requirements
- Budget periods cannot overlap with any existing budget for the campaign.
end_datemust always be later thanstart_date.total_budgetmust be at least 25.00. A value of0is not valid and will return an error.- We recommend budget records that align to calendar months whenever possible (avoid cross-month budget periods) and have a minimum duration of 7 days.
Rather than creating a new campaign each month, keep the existing campaign active and create a new monthly budget record. This allows ZipRecruiter to retain historical campaign performance data and continue optimizing delivery.
Updating Existing Budgets
Budget updates are performed using a PUT request. Only the fields being updated need to be included, except start_date, which must be included on every PUT with its original value. Budget records may only be updated while they remain valid, and date updates cannot create overlapping budget periods.
| Field | Can I Update? | Notes |
|---|---|---|
| Budget cap | ✅ | May be increased at any time. Cannot be reduced below current spend. |
start_date | ⚠️ Future budgets only | Locked once the budget becomes active. |
end_date | ✅ | Must remain after start_date and cannot overlap another budget. |
If a request attempts to lower the budget below the current spend, the API returns 200 OK, automatically adjusts the budget cap to the amount already spent, and returns a warning: "Budget Cap was adjusted from 55.00 to 153.12 because it cannot be set lower than the current amount used."
Once a budget becomes the current budget, its start_date is locked. For example, if a budget's start_date was set to 2025-07-30 on that same day, the record is marked as the current budget, which locks the start_date from further changes. Future budget records may have their start_date updated provided the revised dates do not overlap another budget period.
Creating New Budgets
- The new budget period cannot overlap an existing budget.
- If another budget already exists, the new
start_dateshould begin the day after the previous budget'send_date. - Future budgets may be created in advance provided their dates do not overlap any existing budget records.
Recommended best practices:
- Use monthly budget records instead of creating new campaigns each month.
- Avoid budget periods that span multiple calendar months.
- Keep budget periods at least 7 days in length.
- Use Open budgets when no predefined spending cap is desired.
- Maintain continuous, non-overlapping budget periods for uninterrupted campaign delivery.
Managing Bids
Campaigns use either manual bidding or ZipRecruiter's Performance Optimizer, controlled by the zip_managed_bids field. zip_managed_bids is a read-only status indicator in responses: true means ZipRecruiter's automated system is setting bids (the campaign uses Performance Optimizer, or no manual campaign bid was provided); false means bids are managed manually via the campaign bid value.
Manual Bidding
When zip_managed_bids = false:
- If a campaign bid is provided below the minimum CPC, it is adjusted upward to the applicable minimum and the response includes a warning.
- The minimum campaign bid is 0.61 for most countries, regardless of currency; for GB, DE, and IE campaigns the minimum depends on whether the account is Job Board or Enterprise (Agency/Staffing/Direct).
- If the campaign bid is omitted (
null), ZipRecruiter assigns the applicable minimum as the starting bid, and any CPC values supplied in the XML feed are respected (if available). No validation error is returned when the campaign bid is omitted.
Performance Optimizer
When Performance Optimizer is enabled (zip_managed_bids = true), ZipRecruiter's bidding technology automatically manages and updates CPC bids at the job level using machine learning. Rather than relying on a fixed campaign bid, Performance Optimizer continuously adjusts bids based on factors including historical conversion rates, budget utilization, campaign performance, market competition, campaign objective, and Target Cost Per Apply (when applicable).
When Performance Optimizer is enabled:
- Any campaign
bidvalue provided in the API request is ignored. - Any CPC values included at the job level in the XML feed are ignored.
- ZipRecruiter automatically manages bidding across all jobs within the campaign.
Campaign Objectives
Performance Optimizer supports two optimization objectives, managed via the campaign_objective field. If omitted or null, the campaign optimizes toward the account-level objective by default. The read-only is_apply_volume response field reports the effective objective: true for apply_volume, false for cost_per_apply.
Cost Per Apply (default). Performance Optimizer uses the campaign's target_cpa to automatically adjust bids with the goal of achieving applications at or near the desired cost. When using Cost Per Apply, target_cpa is required. Best for campaigns with established CPA goals, budget-sensitive recruiting, and long-running hiring initiatives.
"campaign_objective": "cost_per_apply"
Apply Volume. Maximizes the number of applications as quickly as possible. Instead of optimizing toward a customer-provided Target CPA, ZipRecruiter calculates an optimal CPA using real-time marketplace data and automatically adjusts bids to maximize application volume. Any target_cpa value provided is ignored, and while apply_volume is on, target_cpa cannot be overridden via API. Best for urgent hiring needs, hard-to-fill positions, campaigns without a defined CPA target, and campaigns with historically uncompetitive Target CPA values.
For optimal performance, we recommend only enabling Apply Volume at the start of new flights (e.g., at budget creation).
"campaign_objective": "apply_volume"
Bid behavior summary:
zip_managed_bids | Campaign bid | Feed CPCs | Result |
|---|---|---|---|
true | Any value | Any value | Both ignored. Performance Optimizer manages bidding. |
false | ≥ 0.61 | Any | Campaign bid is accepted. |
false | null | Present | Campaign defaults to the applicable platform minimum; feed CPCs are respected. |
false | null | None | Campaign defaults to the applicable platform minimum. |
false | < 0.61 | Any | Campaign defaults to the applicable platform minimum. |
Managing Jobs
The Campaign Management API supports two methods of job ingestion, depending on the campaign's apply type:
| Apply Type | XML Feed | Job API |
|---|---|---|
| External Apply | ✅ Required | ❌ Not Supported |
| ZipApply | ✅ Supported | ✅ Optional |
XML feed. Campaigns can ingest jobs from an XML feed hosted over HTTPS or FTP. The feed URL must be provided in RFC 1738 format (e.g., ftp://user:password@ftp.ziprecruiter.com/feeds/example-feed.xml). FTP usernames and passwords must be URI encoded, and if the FTP server uses a port other than 22, the port must be specified in the hostname (e.g., ftp.ziprecruiter.com:24).
Job API. The Job API is supported for ZipApply campaigns only and provides an alternative to XML feed ingestion.
ZipApply vs. External Apply
The API supports both External Apply and ZipApply campaigns. While the request structure is largely the same, there are several behavioral differences:
| Feature | External Apply | ZipApply |
|---|---|---|
| XML Feed | Required | ✅ Supported |
| Job API | ❌ Not Supported | ✅ Supported |
feed_url | Required and used for ingestion | Ignored (uses preconfigured feed) |
| Feed configuration | Passed in API request | Configured internally |
| Candidate delivery | External Apply | ATS/API endpoint configured separately |
partner_attributes | Must be included in request body | Automatically appended |
| Interview screening questions | ❌ Not Supported | ✅ Supported |
| Candidate location filtering | ❌ Not Supported | ✅ Supported |
External Apply campaigns ingest jobs via an XML feed; the feed_url provided in the API request is used to ingest jobs. The Job API is not available for External Apply campaigns.
ZipApply campaigns ingest jobs via an XML feed or, optionally, via the Job API:
- Job ingestion uses a preconfigured internal XML feed associated with the account. The feed URL must be configured by ZipRecruiter before campaigns can be created.
- For accounts where a ZipApply feed has been pre-configured, the
feed_urlfield is ignored and may be included in the API request without issue. - Only one feed per account/employer is supported. Jobs are filtered using a unique identifier (for example,
campaign_id). - The candidate delivery destination (such as an ATS integration or Apply Webhook) must be configured before campaigns begin receiving applicants.
ZipApply must be enabled at the account level before ZipApply campaigns can be created. Once enabled, all campaigns created under that account default to the ZipApply apply flow (onsite). Employers running campaigns with both apply flows require two separate Marketplace accounts/account IDs.
The Campaign Management API request structure does not change for ZipApply campaigns. Any required technical changes apply only to feed formatting and candidate delivery configuration, depending on the delivery method.
Tracking Configuration
Tracking behavior differs based on the campaign's apply type.
External Apply
External Apply campaigns support URL-based tracking using the url_append field, commonly used to append the ZipRecruiter click identifier ([click_id]) to job URLs so it can be logged and passed back through the Conversion API. Available macros:
| Macro | Description |
|---|---|
[click_id] | ZipRecruiter click identifier |
[cpc] | Base64 URL-safe encoded CPC |
[time] | Click timestamp |
The [cpc] and [time] macros are typically only needed when a Cost File integration has not been configured.
UTM parameters and source tracking may be configured at the feed level (add tracking parameters directly to job URLs in the XML feed on a per-job basis) or at the campaign level via url_append, which applies the same tracking parameters across every job in the campaign:
"url_append": "&cid=[click_id]&source=ziprecruiter&utm_source=ziprecruiter"
When processing the url_append value: if the value does not begin with &, one is automatically added; if the destination URL does not already contain a query string, the leading & is converted to ?.
ZipApply
ZipApply campaigns do not use external job URLs. As a result, url_append is ignored, UTM tags are not supported, and campaign-level URL/source tracking is not supported.
Instead, source tracking is configured within the XML feed using the optional tracking_code field under partner_attributes:
<partner_attributes>
<tracking_code>campaign_123</tracking_code>
</partner_attributes>
The tracking_code value is included in both click and conversion files. If tracking_code is not provided, records can be matched using the job_id.
Candidate Location Filtering (ZipApply only)
ZipApply campaigns can optionally use candidate location filters to manage applicant eligibility based on proximity to the job location. This feature can either exclude candidates outside a specified radius or discourage them from applying while still allowing the application to proceed.
| Field | Type | Description |
|---|---|---|
radius | integer | Radius in miles from the job location. Valid range: 10–100 miles. 0 or null disables location filtering. Values from 1–9 are automatically set to 10; values above 100 are capped at 100. |
include_willing_to_relocate | boolean | When true, candidates willing to relocate may be included even when outside the specified radius. When false or null, candidates outside the radius are excluded regardless of relocation preference. |
filter_out_candidates | boolean | Determines how strictly the radius is enforced. When true (default), candidates outside the radius are excluded from delivery and application counts. When false, candidates outside the radius are discouraged from applying but may still apply, be delivered, and count toward application totals. |
In update requests, omitting candidate_location_filter leaves location settings unchanged; setting it to null resets all location settings.
Conversion Data from Your System to ZipRecruiter
For campaigns that use an external redirect (i.e., not ZipApply-enabled), ZipRecruiter relies on partners to share conversion data in order to accurately measure performance and provide meaningful recommendations.
The Conversion API (server-to-server) is the recommended method for reporting conversion events when applications are completed on an external site:
- ZipRecruiter appends a unique click identifier to each job URL.
- The partner submits successful conversion events to ZipRecruiter.
- Each conversion record must include the unique click identifier, the conversion timestamp, an application ID, and the name of the third-party platform.
In limited use cases, a client-side tracking pixel may be used as an alternative: a 1×1 pixel placed on the post-conversion ("Thank You") page, unique to each customer, reporting a conversion event each time a user reaches the page:
<img src="https://track.ziprecruiter.com/conversion?enc_account_id=abc123" width="1" height="1" />
The tracking pixel is available for select use cases; the server-to-server Conversion API provides more reliable conversion reporting and is the recommended integration method. Both approaches support conversion reporting after an external redirect without requiring personal data — only the conversion event itself is recorded.
Implementation details are in the Data Integrations documentation.
Click & Conversion Data from ZipRecruiter to Your System
As a prerequisite for using the Campaign Management API, partners must integrate with a Data Sharing Partner (DSP) to enable delivery of click and conversion files. Data sharing is provided through a cost file integration, where click and/or conversion data is delivered to an (S)FTP server at 15-minute, daily, and monthly intervals.
If a DSP configuration already exists, no additional setup is required. For new DSP integrations, provide the following (S)FTP details: hostname, username, password, and path (optional).
Delivery cadence:
- 15-minute files (intra-day): events in batches of 15 minutes of activity. Files always contain exactly 15 minutes worth of events, and the four files are delivered at the same time, around the top of the hour, to the same location. The time lapse for the 15m files is roughly 3 hours.
- Daily files (7-day lookback): events from the last 7 complete days, shared daily, allowing a true-up of re-published data within a day of re-publication. Can also be used without intra-day feeds.
- Monthly files: events from the previous calendar month in a single large feed, useful for auditing and true-up of intra-day feeds.
Notes:
- Each file contains click and conversion events for all customers included in your DSP configuration.
- The 15-minute files are provided as a convenience for partners that rely on near-real-time reporting. Because events may be removed or restated throughout the day, these files should not be used for reconciliation. If intra-day reporting is not required, you may request only the daily and monthly files.
- We recommend using the 7-day lookback ("daily") files as the source of truth (especially for corrections or true-ups), as they contain the most accurate and finalized click data.
- Marketplace data is timestamped in PST, while the cost files are in UTC — account for the ~8-hour time difference in your analytics.
Implementation details are in the Data Integrations documentation.
Testing Requirements
Before testing your integration, coordinate with your ZipRecruiter Enterprise Solutions Consultant or support team to obtain a dedicated test account and verify your implementation approach.
Coordinate with your ZipRecruiter support team before testing. All testing runs against production systems.
Test account guidelines:
- Use only the
encrypted_account_idprovided for testing. - Include "TEST" in the campaign name to help identify test campaigns.
- Set the budget
io_numberto "TEST" so any test spend can be identified and zeroed out by our Billing team. - Clearly identify all test jobs as test postings within the job title and/or description to discourage job seeker engagement.
- Use the minimum supported CPC of 0.61 and the minimum budget of 25.00 to minimize traffic to test jobs.
Recommended test scenarios before onboarding a production customer:
- Campaign lifecycle operations (
POST,GET,PUT) - Budget creation and updates
- Campaign status changes (
Active,Paused,Cancelled, and reactivation ofAuto-Disabledcampaigns) - XML feed formatting and validation
- Campaign filtering and filter rule behavior
- Job ingestion and synchronization
- Candidate delivery integration (ZipApply)
tracking_codeconfiguration (ZipApply), if applicable
Limitations
- New campaigns must be created in
Pausedstatus. - Minimum budget: $25. Minimum CPC: $0.61 for most countries; GB, DE, and IE minimums vary by account type.
- Budget updates must always include the original
start_date; other fields may be omitted if unchanged. - Budgets cannot have overlapping date ranges.
- Rate limit: 5 simultaneous requests per API key, queue of 10. Exceeding returns
503. - Timeout: 120 seconds (returns
504). - No batch endpoint — one object per API call.
Errors
Error responses return {"errors": ["<error message>"]}. Validation errors follow the format associated_input_param: <field>, code: <code>, message: <description>.
Campaign Errors (Create/Update)
| Status | Field | Code | Message |
|---|---|---|---|
| 400 | name | missing_name | "name cannot be empty" |
| 400 | feed_url | missing_feed_url | "feed_url cannot be empty" |
| 400 | feed_url | invalid_feed_url | "feed_url must be a valid url" |
| 400 | feed_url | missing_ftp_username | "feed_url must have a username:password when set to a ftp url" |
| 400 | feed_url | missing_ftp_password | "feed_url must have a username:password when set to a ftp url" |
| 400 | country | missing_country | "country cannot be empty" |
| 400 | status | invalid_status | "status must be one of: Active, Paused, Cancelled" |
| 400 | campaign_objective | invalid_campaign_objective | "campaign_objective must be either 'cost_per_apply' or 'apply_volume'" |
| 400 | target_cpa | missing_target_cpa | "target_cpa is required when campaign_objective is set to 'cost_per_apply'" |
| 400 | feed_filters | invalid_feed_filters | "feed_filters[N].rule must be one of: include, exclude" |
| 400 | feed_filters | invalid_feed_filters | "feed_filters[N].value must not contain a comma-space or double quotes" |
Budget Errors (Create/Update)
| Status | Field | Code | Message |
|---|---|---|---|
| 400 | start_date | missing_start_date | "start_date cannot be empty" |
| 400 | start_date | invalid_start_date | "invalid start date format, want yyyy-MM-dd" |
| 400 | start_date | invalid_start_date | "start date cannot be before today (in America/Los_Angeles timezone)" |
| 400 | end_date | missing_end_date | "end_date cannot be empty" |
| 400 | end_date | invalid_end_date | "invalid end date format, want yyyy-MM-dd" |
| 400 | end_date | invalid_end_date | "budget cannot be more than 365 days in length" |
| 400 | end_date | invalid_end_date | "end_date must be after start date" |
| 400 | end_date | invalid_end_date | "end date cannot be before today (in America/Los_Angeles timezone)" (update only) |
| 400 | total_budget | invalid_total_budget | "total_budget must be greater than 25" (the check is inclusive: exactly 25.00 is accepted) |
| 400 | total_budget | invalid_total_budget | "if budget_cap_type is open, total_budget must not be submitted" |
| 400 | total_budget | missing_total_budget | "total_budget missing from request body" |
| 400 | budget_cap_type | invalid_budget_cap_type | "budget_cap_type must be 'fixed' or 'open'" |
| 400 | budget_cap_type | invalid_budget_cap_type | "updating a budget to have an 'open' budget is not currently supported, if you are authorized to use the 'open' budget type, please close the current budget by setting the end date to today, and create a new budget with 'open' budget type and a start date of tomorrow or later" |
Budget Warnings (200 OK)
Successful budget create/update responses may include a warnings array:
| Scenario | Warning |
|---|---|
Bid provided but campaign has zip_managed_bids enabled | "Campaign is set on zip managed bids, so bid value 0.XX will be ignored" |
| Bid below minimum CPC for GB/DE/IE campaigns | "Bid value X.XX was below our minimum CPC bid for {country} campaigns and has been adjusted to X.XX" |
| Bid below global minimum CPC (0.61) for non-European campaigns | "Bid value X.XX was below minimum CPC bid of 0.61 and has been adjusted to 0.61" |
| Budget was lowered to a value under the current spend | "Budget Cap was adjusted from XX.XX to XX.XX because it cannot be set lower than the current amount used." |
Other Errors
| Status | Error | Scenario |
|---|---|---|
| 400 | Malformed Request Body | The JSON request body cannot be parsed |
| 400 | Invalid Resource ID | An account, campaign, or budget ID in the URL path is not valid |
| 401 | Unauthorized | Authentication fails (missing header, invalid or inactive API key, incorrect password — all produce the same response) |
| 404 | Not Found | The account, campaign, or budget ID does not exist, or the URL path does not match a valid endpoint |
| 405 | Method Not Allowed | An unsupported HTTP method was used on an endpoint |
| 408 | Request Timeout | The server was unable to complete the request in time |
| 500 | Internal Server Error | An unexpected server-side error occurred; not caused by your input |
API Reference
Full request/response schemas for every endpoint: Campaign Management API Reference. For questions during implementation, contact your ZipRecruiter support team.