Skip to main content

Healthcare Professional (HCP) Planner

Use the Healthcare Professional (HCP) Planner to build, save, and publish an HCP plan as an insertion order (IO) and campaigns with this in-depth tutorial using IQM's Planner API.

The following endpoints are used to generate campaigns, save a plan, and publish it:

POST
POST
POST
GET
PUT
POST
POST

About HCP plans​

An HCP plan targets healthcare professionals by their National Provider Identifier (NPI) type, specialty, location, and data partner. Unlike Political plans, which go through separate strategy and proposal stages, an HCP plan is created directly with its targeting and proposed campaigns. Endpoints and fields that refer to a proposal, such as /hcp/proposal/add, work with the same HCP plan, and the plan's ID is used wherever a planId is required.

Generate campaigns → Save plan → Edit (optional) → Publish IO and campaigns

There are two key rules to keep in mind when working with HCP plans:

  1. Targeting consistency: The split strategy must agree with the plan-level targeting when you save, edit, or publish the plan. See Step 1.
  2. Status echo: Every edit and publish request must include the plan's current statusId. See Step 5.

More resources​

Before you begin​

To create and publish an HCP plan, the following are required:

  • An account on the IQM platform in a Healthcare Workspace
    • See the Getting started section to create an account and request a Client ID and Client Secret.
    • Planner API requests from a Workspace outside the Healthcare vertical are rejected.
  • An Advertiser Organization
    • Publishing and downloading a plan is only available to Advertiser Organizations.

All Planner times are Unix epoch milliseconds, not seconds. For example, November 1, 2026 at 00:00 US/Eastern is 1793505600000.

Log in​

POST

To log in, send the Authorization: Basic header with your Base64-encoded Client ID and Client Secret, and send the request body as form data (application/x-www-form-urlencoded). This endpoint returns an OAuth-compliant response with an access token and an Organization Workspace ID (owId), a unique identifier for each Organization. This ID is used for any further API communications.

For further information, see OAuth token.

Headers
Authorization
string required
Basic followed by your Base64-encoded client_id:client_secret.
See Sign up and authenticate.
Request schema
grant_type
string required
password to log in.
See OAuth grant types.
username
string required
User account email.
password
string required
User account password.
Request sample
curl -i --location 'https://api.iqm.com/api/v3/ua/oauth/token' \
--header 'accept: application/json, text/plain, */*' \
--header 'Authorization: Basic <Client ID/Client Secret>' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=user@iqm.com' \
--data-urlencode 'password=<your password>'
Response 200
{
"success": true,
"data":
{
"access_token": "106adb25-37b0-4cab-8381-d682fe7cc3c8",
"refresh_token": "eac4c1f6-781e-4b04-baff-9c2e415d1f64",
"scope": "read write",
"token_type": "bearer",
"expires_in": 35999,
"owId": 200001
}
}
More responses
Response 400
{
"success": false,
"data":
{
"status": "On Hold",
"reason": "The particular account is kept on hold due to missed payment dates for last 3 months.",
"supportEmail": "support@iqm.com"
},
"errorObjects":
[
{
"error": "User is not allowed to access provided customer",
"reason": "User is not associated with any active organization."
}
]
}
Response 403
{
"success": false,
"errorObjects":
[
{
"error": "User doesn't exist or user is not allowed to provided workspace."
}
]
}

Authentication​

Use the following header parameters for all requests after logging in:

Headers
Authorization
string required
Bearer followed by the access_token from the login response.
See Sign up and authenticate.
X-IAA-OW-ID
integer required
Organization Workspace ID header.

Create an HCP plan using the IQM API​

This tutorial covers the following steps:

  1. Plan the audience and targeting
  2. Generate campaigns
  3. Create a plan
  4. Get plan details
  5. Edit the plan
    • Optional
  6. Publish the IO and campaigns
  7. Download the plan
    • Optional

Step 1: Plan the audience and targeting​

Before calling any endpoint, decide who the plan targets and how its campaigns are split. These choices make up the body of every request in the following steps. See HCP Planner resource properties for all fields.

NPI types​

npiTypeIds sets which professionals to reach. Get values from the NPI type list.

Supported values
3HCP
4NPI nurse

Audience blocks​

audienceBlocks defines the audience. Each block uses one audience selection method, set by audienceSelectionMethodId, and the fields a block needs depend on its method. Use at most one block per method. See Get audience selection methods list.

MethodIDRequired block fieldsAudience type
Filter based1speciality, locations, dataPartnersMatched audience (1)
Upload NPI list2speciality, locations, dataPartners, and storagePathId from an uploaded NPI fileMatched audience (1)
Existing audience3includeAudienceIds and/or excludeAudienceIds, up to 14 in total. Don't send specialty, location, or data partner fields.Taken from the selected audiences
Account based4speciality, locations, account, accountType, healthSystem, title, dataPartners. Requires NPI type 3.Account Based Marketing (ABM) audience (9)

For filter-based blocks:

  • locations.countryId must be 30100001 (United States).
  • dataPartners is a list of partners with at least one marked selected: true. See Get data partners list; the active partners are 7, 8, 11, and 12.
  • speciality uses the "select all" pattern described below. See Get specialties list.

The audience type of each block is set by IQM from its method, as in the table above. Don't send selectedAudienceTypeIds; it is ignored.

Plan-level targeting​

planLevelTargeting sets the creative types, devices, channels, and inventory for the whole plan. All four objects are required: a request without channels or inventory returns a generic 500 error. To target all channels and all Open Exchange inventory, send:

Channels and inventory, all selected
"channels": {
"channelTypeIds": [],
"allChannelTypesSelected": true
},
"inventory": {
"openExchanges": {
"exchangeIds": [],
"allExchangesSelected": true,
"iabCategoryIds": [],
"allIabCategoriesSelected": true
}
}

Objects such as creativeTypes, devices, channels, and speciality use a "select all" flag with an ID list:

  • Select all: set the flag (for example allCreativeTypesSelected) to true and send an empty ID list.
  • Select specific values: set the flag to false and list the IDs.

Any other combination is rejected.

Split strategy and the targeting consistency rule​

splitStrategy decides how the plan is divided into campaigns. Each entry names a split dimension and the values to split by. Each listed value becomes its own campaign slice, and campaigns are created for every combination of slices. A split strategy must include the creative type dimension, and the NPI type dimension unless the only audience block is an existing audience.

The values in each split dimension must agree with the plan's targeting when you save, edit, or publish the plan (Steps 3, 5, and 6). This is the most common cause of rejected HCP requests. Generating campaigns (Step 2) doesn't check the rule: it ignores selectedValueIds and splits by every plan-level value of each listed dimension. For example, an NPI type split of [3] on a plan targeting NPI types 3 and 4 still creates campaigns for both. See Targeting consistency rule.

Split dimensionsplitDimensionTypeIdselectedValueIds must agree withRuleCampaign field
Creative type1planLevelTargeting.creativeTypes.creativeTypeIdsExact matchtargeting.creativeTypeId
NPI type2npiTypeIdsSubsettargeting.npiTypeId
Data partner3dataPartners[].id across all audience blocksSubsettargeting.dataPartnerIds
Device type4planLevelTargeting.devices.deviceTypeIdsSubsettargeting.deviceTypeIds
Audience type5Audience types of all audience blocksSubsettargeting.audienceTypeIds

When "select all" is used for creative types or devices, compare against the full list: creative types 11, 13, 14, 15, and 17; devices 20300001 to 20300004.

caution

Mismatches are reported with a general message, such as Selected creative type IDs and split IDs do not match. Check the dimension named in the message against the table above.

Each proposed campaign's targeting uses singular fields for creative and NPI type (creativeTypeId, npiTypeId), unlike the plural fields at the plan level. Campaign targeting isn't checked against the split strategy, so let IQM build the campaigns in Step 2 rather than writing them yourself.

Step 2: Generate campaigns​

POST

Send the plan details from Step 1 without campaigns. IQM builds the proposed campaigns from the split strategy, forecasts their reach, and calculates each campaign's CPM, impressions, and budget range, along with the plan's totals. Nothing is saved.

Use the response as the request body for Step 3. You can change budgets and impressions within each campaign's minimum and maximum before saving.

Each campaign's dataCpm is the average data cost of its selected data partners, and its mediaCpm depends on its creative type. For example, video campaigns have a higher media CPM than image campaigns.

Request schema
name
string required
Plan name; must be unique in the Workspace.
startTime
integer required
Unix epoch start time in milliseconds; can't be in the past.
endTime
integer required
Unix epoch end time in milliseconds; must be at least 30 minutes after startTime.
timezoneId
integer required
Timezone ID.
budgetTypeId
integer required
Budget type ID.
Supported values
1Budget
2Impression
frequencyCap
integer required
Frequency cap, 1 to 99.
frequencyCapTypeId
integer required
Frequency cap type ID.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
npiTypeIds
array of integers required
NPI type IDs.
Supported values
3HCP
4NPI nurse
audienceBlocks
array of objects required
Audience blocks, at most one per audience selection method.
audienceBlocks object properties
audienceSelectionMethodId
integer required
Audience selection method ID. Account based blocks need additional account, health system, and title fields.
Supported values
1Filter based
2Upload NPI list
3Existing audience
4Account based
speciality
object
Specialties to target. Required for filter based, upload NPI list, and account based blocks.
speciality object properties
allSpecialitiesSelected
boolean required
Set to true to target all specialties, with an empty specialityIds list. Set to false to target only the listed specialties.
specialityIds
array of integers
Specialty IDs to target. Must be empty when allSpecialitiesSelected is true.
locations
object
Locations to target. Required for filter based, upload NPI list, and account based blocks.
locations object properties
countryId
integer required
Country ID; must be 30100001 (United States).
whiteListedStateIds
array of integers
State IDs to target.
blackListedStateIds
array of integers
State IDs to exclude.
whiteListedCityIds
array of integers
City IDs to target.
blackListedCityIds
array of integers
City IDs to exclude.
whiteListedZipcodes
array of strings
ZIP codes to target.
blackListedZipcodes
array of strings
ZIP codes to exclude. Targeted and excluded locations can't overlap.
dataPartners
array of objects
Data partners to match the audience with. At least one must be selected. Required for filter based, upload NPI list, and account based blocks.
dataPartners object properties
id
integer required
Data partner ID. Account based blocks support only 7 and 12.
Supported values
7Healthlink
8Data360
11Purple Lab
12RevOptimal
selected
boolean required
Set to true to use this data partner.
priority
integer
Order of preference, starting at 1; can't be higher than the number of data partners in the block.
reach
integer
Data partner reach.
incrementalReach
integer
Reach this data partner adds on top of higher-priority data partners; 0 to reach.
storagePathId
integer
Upload NPI list blocks only: file ID of the uploaded NPI list.
includeAudienceIds
array of integers
Existing audience blocks only: audience IDs to include. Up to 14 included and excluded audiences in total.
excludeAudienceIds
array of integers
Existing audience blocks only: audience IDs to exclude. Can't overlap with includeAudienceIds.
planLevelTargeting
object required
Creative type, device, channel, and inventory targeting for the whole plan.
planLevelTargeting object properties
creativeTypes
object required
Creative types to target.
creativeTypes object properties
allCreativeTypesSelected
boolean required
Set to true to target all creative types, with an empty creativeTypeIds list. Set to false to target only the listed creative types.
creativeTypeIds
array of integers
Creative type IDs to target. Must be empty when allCreativeTypesSelected is true.
Supported values
11Image
13HTML
14Video
15Native
17Audio
isTvAutoBuying
boolean
Whether TV auto buying is enabled; requires video creatives (14).
devices
object required
Devices to target.
devices object properties
allDeviceTypesSelected
boolean required
Set to true to target all device types, with an empty deviceTypeIds list. Set to false to target only the listed device types.
deviceTypeIds
array of integers
Device type IDs to target. Must be empty when allDeviceTypesSelected is true.
Supported values
20300001Mobile
20300002Desktop
20300003Connected TV
20300004Tablet
channels
object required
Channels to target.
channels object properties
allChannelTypesSelected
boolean required
Set to true to target all channels, with an empty channelTypeIds list.
channelTypeIds
array of integers
Channel type IDs to target. Must be empty when allChannelTypesSelected is true.
Supported values
11App
14CTV
13OTT
12Web
inventory
object required
Inventory to target.
inventory object properties
openExchanges
object required
Open Exchange inventory to target.
openExchanges object properties
allExchangesSelected
boolean required
Set to true to target all exchanges, with an empty exchangeIds list.
exchangeIds
array of integers
Exchange IDs to target.
allIabCategoriesSelected
boolean required
Set to true to target all IAB categories, with an empty iabCategoryIds list.
iabCategoryIds
array of integers
IAB category IDs to target.
inventoryGroup
object
Inventory groups to target. Send null or leave it out when you don't target inventory groups.
splitStrategy
array of objects required
Split dimensions used to divide the plan into campaigns. Must include the creative type dimension, and the NPI type dimension unless the only audience block is an existing audience block.
splitStrategy object properties
splitDimensionTypeId
integer required
Split dimension ID. Each dimension can appear once.
Supported values
1Creative type
2NPI type
3Partner
4Device type
5Audience type
selectedValueIds
array of integers required
Values to split by. Ignored when generating campaigns: every plan-level value of the dimension becomes its own campaign slice. Saving, editing, and publishing check them: creative type must exactly match the plan-level creative types, and other dimensions must be a subset of the matching targeting.
Response properties

The response contains every request field, plus:

minBudget, budget, maxBudget
number
Plan budget range and suggested budget.
minImpressions, impressions, maxImpressions
integer
Plan impressions range and suggested impressions.
reach, maxReach
integer
Forecasted reach.
campaigns
array of objects
Proposed campaigns, sorted by reach.
campaigns object properties
name
string
Campaign name.
startTime, endTime
integer
Unix epoch start and end time in milliseconds.
minMediaCpm, mediaCpm, maxMediaCpm
number
Media cost per mille (CPM) range.
dataCpm
number
Data CPM, based on the selected data partners.
minBudget, budget, maxBudget
number
Campaign budget range.
minReach, reach, maxReach
integer
Campaign reach range.
minImpressions, impressions, maxImpressions
integer
Campaign impressions range.
isAbm
boolean
Whether the campaign targets an ABM audience.
targeting
object
Campaign targeting: creativeTypeId, npiTypeId, dataPartnerIds, deviceTypeIds, audienceTypeIds.
Request sample
{
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"npiTypeIds": [3, 4],
"audienceBlocks": [
{
"audienceSelectionMethodId": 1,
"speciality": {
"specialityIds": [],
"allSpecialitiesSelected": true
},
"locations": {
"countryId": 30100001,
"whiteListedStateIds": [],
"blackListedStateIds": [],
"whiteListedCityIds": [],
"blackListedCityIds": [],
"whiteListedZipcodes": [],
"blackListedZipcodes": []
},
"dataPartners": [
{ "id": 7, "selected": true, "priority": 1 },
{ "id": 8, "selected": true, "priority": 2 }
]
}
],
"planLevelTargeting": {
"devices": {
"deviceTypeIds": [20300001, 20300004],
"allDeviceTypesSelected": false
},
"creativeTypes": {
"creativeTypeIds": [11, 14],
"allCreativeTypesSelected": false,
"isTvAutoBuying": false
},
"channels": {
"channelTypeIds": [],
"allChannelTypesSelected": true
},
"inventory": {
"openExchanges": {
"exchangeIds": [],
"allExchangesSelected": true,
"iabCategoryIds": [],
"allIabCategoriesSelected": true
}
}
},
"splitStrategy": [
{ "splitDimensionTypeId": 1, "selectedValueIds": [11, 14] },
{ "splitDimensionTypeId": 2, "selectedValueIds": [3, 4] }
]
}
Response 200 (abbreviated)
{
"success": true,
"data": {
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"minBudget": 98.00,
"budget": 8820.00,
"maxBudget": 8820.00,
"reach": 60000,
"maxReach": 60000,
"minImpressions": 4000,
"impressions": 360000,
"maxImpressions": 360000,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"npiTypeIds": [3, 4],
"audienceBlocks": [ ... ],
"planLevelTargeting": { ... },
"splitStrategy": [ ... ],
"campaigns": [
{
"id": null,
"name": "Video - Physicians",
"startTime": 1793505600000,
"endTime": 1796101199000,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"minMediaCpm": 18.00,
"mediaCpm": 18.00,
"maxMediaCpm": 18.00,
"dataCpm": 12.50,
"minBudget": 30.50,
"budget": 3843.00,
"maxBudget": 3843.00,
"minReach": 10,
"reach": 42000,
"maxReach": 42000,
"minImpressions": 1000,
"impressions": 126000,
"maxImpressions": 126000,
"isAbm": false,
"targeting": {
"dataPartnerIds": [7, 8],
"creativeTypeId": 14,
"deviceTypeIds": [20300001, 20300004],
"npiTypeId": 3,
"audienceTypeIds": [1]
}
},
...
]
}
}

Step 3: Create a plan​

POST
POST

Save the plan in Ready (6) status using the /add endpoint. Send the full response data from Step 2 as the request body, unchanged apart from any budgets and impressions you adjust within their ranges. Saving doesn't check that the plan totals match the campaigns, so a modified body is saved as sent. Save the id from the response; it's the planId used in the following steps.

To save an incomplete plan instead, use the /draft endpoint, which saves it in Draft (2) status and skips the budget and campaign checks. See Create HCP Planner.

Request schema
name
string required
Plan name; must be unique in the Workspace.
startTime
integer required
Unix epoch start time in milliseconds; can't be in the past.
endTime
integer required
Unix epoch end time in milliseconds; must be at least 30 minutes after startTime.
timezoneId
integer required
Timezone ID.
budgetTypeId
integer required
Budget type ID.
Supported values
1Budget
2Impression
minBudget
number required
Minimum plan budget, from Step 2.
budget
number required
Plan budget; must be between minBudget and maxBudget.
maxBudget
number required
Maximum plan budget, from Step 2.
minImpressions
integer required
Minimum plan impressions, from Step 2.
impressions
integer required
Plan impressions; must be between minImpressions and maxImpressions.
maxImpressions
integer required
Maximum plan impressions, from Step 2.
reach
integer
Forecasted reach, from Step 2.
maxReach
integer
Maximum forecasted reach, from Step 2.
frequencyCap
integer required
Frequency cap, 1 to 99.
frequencyCapTypeId
integer required
Frequency cap type ID.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
npiTypeIds
array of integers required
NPI type IDs.
Supported values
3HCP
4NPI nurse
audienceBlocks
array of objects required
Audience blocks, at most one per audience selection method.
audienceBlocks object properties
audienceSelectionMethodId
integer required
Audience selection method ID. Account based blocks need additional account, health system, and title fields.
Supported values
1Filter based
2Upload NPI list
3Existing audience
4Account based
speciality
object
Specialties to target. Required for filter based, upload NPI list, and account based blocks.
speciality object properties
allSpecialitiesSelected
boolean required
Set to true to target all specialties, with an empty specialityIds list. Set to false to target only the listed specialties.
specialityIds
array of integers
Specialty IDs to target. Must be empty when allSpecialitiesSelected is true.
locations
object
Locations to target. Required for filter based, upload NPI list, and account based blocks.
locations object properties
countryId
integer required
Country ID; must be 30100001 (United States).
whiteListedStateIds
array of integers
State IDs to target.
blackListedStateIds
array of integers
State IDs to exclude.
whiteListedCityIds
array of integers
City IDs to target.
blackListedCityIds
array of integers
City IDs to exclude.
whiteListedZipcodes
array of strings
ZIP codes to target.
blackListedZipcodes
array of strings
ZIP codes to exclude. Targeted and excluded locations can't overlap.
dataPartners
array of objects
Data partners to match the audience with. At least one must be selected. Required for filter based, upload NPI list, and account based blocks.
dataPartners object properties
id
integer required
Data partner ID. Account based blocks support only 7 and 12.
Supported values
7Healthlink
8Data360
11Purple Lab
12RevOptimal
selected
boolean required
Set to true to use this data partner.
priority
integer
Order of preference, starting at 1; can't be higher than the number of data partners in the block.
reach
integer
Data partner reach.
incrementalReach
integer
Reach this data partner adds on top of higher-priority data partners; 0 to reach.
storagePathId
integer
Upload NPI list blocks only: file ID of the uploaded NPI list.
includeAudienceIds
array of integers
Existing audience blocks only: audience IDs to include. Up to 14 included and excluded audiences in total.
excludeAudienceIds
array of integers
Existing audience blocks only: audience IDs to exclude. Can't overlap with includeAudienceIds.
planLevelTargeting
object required
Creative type, device, channel, and inventory targeting for the whole plan.
planLevelTargeting object properties
creativeTypes
object required
Creative types to target.
creativeTypes object properties
allCreativeTypesSelected
boolean required
Set to true to target all creative types, with an empty creativeTypeIds list. Set to false to target only the listed creative types.
creativeTypeIds
array of integers
Creative type IDs to target. Must be empty when allCreativeTypesSelected is true.
Supported values
11Image
13HTML
14Video
15Native
17Audio
isTvAutoBuying
boolean
Whether TV auto buying is enabled; requires video creatives (14).
devices
object required
Devices to target.
devices object properties
allDeviceTypesSelected
boolean required
Set to true to target all device types, with an empty deviceTypeIds list. Set to false to target only the listed device types.
deviceTypeIds
array of integers
Device type IDs to target. Must be empty when allDeviceTypesSelected is true.
Supported values
20300001Mobile
20300002Desktop
20300003Connected TV
20300004Tablet
channels
object required
Channels to target.
channels object properties
allChannelTypesSelected
boolean required
Set to true to target all channels, with an empty channelTypeIds list.
channelTypeIds
array of integers
Channel type IDs to target. Must be empty when allChannelTypesSelected is true.
Supported values
11App
14CTV
13OTT
12Web
inventory
object required
Inventory to target.
inventory object properties
openExchanges
object required
Open Exchange inventory to target.
openExchanges object properties
allExchangesSelected
boolean required
Set to true to target all exchanges, with an empty exchangeIds list.
exchangeIds
array of integers
Exchange IDs to target.
allIabCategoriesSelected
boolean required
Set to true to target all IAB categories, with an empty iabCategoryIds list.
iabCategoryIds
array of integers
IAB category IDs to target.
inventoryGroup
object
Inventory groups to target. Send null or leave it out when you don't target inventory groups.
splitStrategy
array of objects required
Split dimensions used to divide the plan into campaigns. Must include the creative type dimension, and the NPI type dimension unless the only audience block is an existing audience block.
splitStrategy object properties
splitDimensionTypeId
integer required
Split dimension ID. Each dimension can appear once.
Supported values
1Creative type
2NPI type
3Partner
4Device type
5Audience type
selectedValueIds
array of integers required
Values to split by; each value becomes its own campaign slice. For creative type, must exactly match the plan-level creative types. For other dimensions, must be a subset of the matching targeting.
campaigns
array of objects required
Proposed campaigns from Step 2, up to 250. Each campaign's media CPM, reach, and budget (or impressions, when budgetTypeId is 2) must be within its own range. Every minimum and maximum field is required.
campaigns object properties
name
string required
Campaign name.
startTime
integer required
Unix epoch start time in milliseconds.
endTime
integer required
Unix epoch end time in milliseconds.
frequencyCap
integer
Frequency cap.
frequencyCapTypeId
integer
Frequency cap type ID.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
minMediaCpm
number required
Minimum media cost per mille (CPM).
mediaCpm
number required
Media CPM; must be between minMediaCpm and maxMediaCpm.
maxMediaCpm
number required
Maximum media CPM.
dataCpm
number required
Data CPM, based on the selected data partners.
minBudget
number required
Minimum campaign budget.
budget
number required
Campaign budget; must be between minBudget and maxBudget.
maxBudget
number required
Maximum campaign budget.
minReach
integer required
Minimum campaign reach.
reach
integer required
Campaign reach; must be between minReach and maxReach.
maxReach
integer required
Maximum campaign reach.
minImpressions
integer required
Minimum campaign impressions.
impressions
integer required
Campaign impressions; must be between minImpressions and maxImpressions.
maxImpressions
integer required
Maximum campaign impressions.
isAbm
boolean
Whether the campaign targets an ABM audience.
targeting
object required
Campaign targeting. Each field holds the single value, or group of values, for this campaign's slice of the split strategy.
targeting object properties
creativeTypeId
integer required
Creative type ID.
Supported values
11Image
13HTML
14Video
15Native
17Audio
npiTypeId
integer required
NPI type ID.
Supported values
3HCP
4NPI nurse
dataPartnerIds
array of integers required
Data partner IDs.
Supported values
7Healthlink
8Data360
11Purple Lab
12RevOptimal
deviceTypeIds
array of integers required
Device type IDs.
Supported values
20300001Mobile
20300002Desktop
20300003Connected TV
20300004Tablet
audienceTypeIds
array of integers required
Audience type IDs.
Supported values
1Matched audience
2Segmented audience
4Geofarmed audience
5Contextual audience
9Account Based Marketing (ABM) audience
.
Request sample
{
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"minBudget": 98.00,
"budget": 8820.00,
"maxBudget": 8820.00,
"reach": 60000,
"maxReach": 60000,
"minImpressions": 4000,
"impressions": 360000,
"maxImpressions": 360000,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"npiTypeIds": [3, 4],
"audienceBlocks": [
{
"audienceSelectionMethodId": 1,
"speciality": { "specialityIds": [], "allSpecialitiesSelected": true },
"locations": {
"countryId": 30100001,
"whiteListedStateIds": [],
"blackListedStateIds": [],
"whiteListedCityIds": [],
"blackListedCityIds": [],
"whiteListedZipcodes": [],
"blackListedZipcodes": []
},
"dataPartners": [
{ "id": 7, "selected": true, "priority": 1, "reach": 120000, "incrementalReach": 120000 },
{ "id": 8, "selected": true, "priority": 2, "reach": 90000, "incrementalReach": 30000 }
]
}
],
"planLevelTargeting": {
"devices": { "deviceTypeIds": [20300001, 20300004], "allDeviceTypesSelected": false },
"creativeTypes": { "creativeTypeIds": [11, 14], "allCreativeTypesSelected": false, "isTvAutoBuying": false },
"channels": { "channelTypeIds": [], "allChannelTypesSelected": true },
"inventory": {
"openExchanges": { "exchangeIds": [], "allExchangesSelected": true, "iabCategoryIds": [], "allIabCategoriesSelected": true }
}
},
"splitStrategy": [
{ "splitDimensionTypeId": 1, "selectedValueIds": [11, 14] },
{ "splitDimensionTypeId": 2, "selectedValueIds": [3, 4] }
],
"campaigns": [
{
"name": "Image - Physicians",
"startTime": 1793505600000, "endTime": 1796101199000,
"frequencyCap": 3, "frequencyCapTypeId": 1,
"minMediaCpm": 6.00, "mediaCpm": 6.00, "maxMediaCpm": 6.00, "dataCpm": 12.50,
"minBudget": 18.50, "budget": 2331.00, "maxBudget": 2331.00,
"minReach": 10, "reach": 42000, "maxReach": 42000,
"minImpressions": 1000, "impressions": 126000, "maxImpressions": 126000,
"isAbm": false,
"targeting": { "dataPartnerIds": [7, 8], "creativeTypeId": 11, "deviceTypeIds": [20300001, 20300004], "npiTypeId": 3, "audienceTypeIds": [1] }
},
{
"name": "Image - Nurses",
"startTime": 1793505600000, "endTime": 1796101199000,
"frequencyCap": 3, "frequencyCapTypeId": 1,
"minMediaCpm": 6.00, "mediaCpm": 6.00, "maxMediaCpm": 6.00, "dataCpm": 12.50,
"minBudget": 18.50, "budget": 999.00, "maxBudget": 999.00,
"minReach": 10, "reach": 18000, "maxReach": 18000,
"minImpressions": 1000, "impressions": 54000, "maxImpressions": 54000,
"isAbm": false,
"targeting": { "dataPartnerIds": [7, 8], "creativeTypeId": 11, "deviceTypeIds": [20300001, 20300004], "npiTypeId": 4, "audienceTypeIds": [1] }
},
{
"name": "Video - Physicians",
"startTime": 1793505600000, "endTime": 1796101199000,
"frequencyCap": 3, "frequencyCapTypeId": 1,
"minMediaCpm": 18.00, "mediaCpm": 18.00, "maxMediaCpm": 18.00, "dataCpm": 12.50,
"minBudget": 30.50, "budget": 3843.00, "maxBudget": 3843.00,
"minReach": 10, "reach": 42000, "maxReach": 42000,
"minImpressions": 1000, "impressions": 126000, "maxImpressions": 126000,
"isAbm": false,
"targeting": { "dataPartnerIds": [7, 8], "creativeTypeId": 14, "deviceTypeIds": [20300001, 20300004], "npiTypeId": 3, "audienceTypeIds": [1] }
},
{
"name": "Video - Nurses",
"startTime": 1793505600000, "endTime": 1796101199000,
"frequencyCap": 3, "frequencyCapTypeId": 1,
"minMediaCpm": 18.00, "mediaCpm": 18.00, "maxMediaCpm": 18.00, "dataCpm": 12.50,
"minBudget": 30.50, "budget": 1647.00, "maxBudget": 1647.00,
"minReach": 10, "reach": 18000, "maxReach": 18000,
"minImpressions": 1000, "impressions": 54000, "maxImpressions": 54000,
"isAbm": false,
"targeting": { "dataPartnerIds": [7, 8], "creativeTypeId": 14, "deviceTypeIds": [20300001, 20300004], "npiTypeId": 4, "audienceTypeIds": [1] }
}
]
}
Response 200
{
"success": true,
"data": {
"message": "Q4 Cardiology Awareness generated successfully",
"id": 4512
}
}
More responses
Response 422
{
"success": false,
"errorObjects": [
{
"error": "Selected creative type IDs and split IDs do not match."
}
]
}

Step 4: Get plan details​

GET

Use the id from Step 3 to get the saved plan. The response uses the same fields as the request in Step 3, plus the plan's statusId and ioId.

Use this endpoint to:

  • Get the current statusId before editing or publishing the plan
  • Check the result of publishing in Step 6
Path parameters
planId
integer required
Plan ID from Step 3.
Response properties
id
integer
Plan ID.
name
string
Plan name.
statusId
integer
Current plan status ID. Send this value back unchanged when editing or publishing the plan.
Supported values
2Draft
3Expired
4Failed
5Processing
6Ready
7IO Created
ioId
integer
IO ID generated when the plan is published; 0 until then.
owId
integer
Organization Workspace ID.
startTime
integer
Unix epoch start time in milliseconds.
endTime
integer
Unix epoch end time in milliseconds.
timezoneId
integer
Timezone ID.
createdAt
integer
Unix epoch creation time in milliseconds.
updatedAt
integer
Unix epoch last update time in milliseconds.
budgetTypeId
integer
Budget type ID.
Supported values
1Budget
2Impression
minBudget
number
Always null in this response. Keep the value from Step 2 to edit or publish the plan.
budget
number
Plan budget.
maxBudget
number
Maximum plan budget.
minImpressions
integer
Always null in this response. Keep the value from Step 2 to edit or publish the plan.
impressions
integer
Plan impressions.
maxImpressions
integer
Maximum plan impressions.
reach
integer
Forecasted reach.
maxReach
integer
Maximum forecasted reach.
frequencyCap
integer
Frequency cap.
frequencyCapTypeId
integer
Frequency cap type ID.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
npiTypeIds
array of integers
NPI type IDs.
Supported values
3HCP
4NPI nurse
audienceBlocks
array of objects
Audience blocks.
audienceBlocks object properties
audienceSelectionMethodId
integer
Audience selection method ID.
Supported values
1Filter based
2Upload NPI list
3Existing audience
4Account based
speciality
object
Targeted specialties; null for existing audience blocks.
speciality object properties
allSpecialitiesSelected
boolean
Whether all specialties are targeted.
specialityIds
array of integers
Specialty IDs; empty when all specialties are targeted.
locations
object
Targeted and excluded locations; null for existing audience blocks.
locations object properties
countryId
integer
Country ID.
whiteListedStateIds
array of integers
Targeted state IDs.
blackListedStateIds
array of integers
Excluded state IDs.
whiteListedCityIds
array of integers
Targeted city IDs.
blackListedCityIds
array of integers
Excluded city IDs.
whiteListedZipcodes
array of strings
Targeted ZIP codes.
blackListedZipcodes
array of strings
Excluded ZIP codes.
dataPartners
array of objects
Data partners for the block.
dataPartners object properties
id
integer
Data partner ID.
Supported values
7Healthlink
8Data360
11Purple Lab
12RevOptimal
selected
boolean
Whether the data partner is used.
priority
integer
Order of preference.
reach
integer
Data partner reach.
incrementalReach
integer
Reach this data partner adds on top of higher-priority data partners.
storagePathId
integer
Upload NPI list blocks only: file ID of the uploaded NPI list.
storageFileName
string
Upload NPI list blocks only: name of the uploaded NPI list file.
storageFileRows
integer
Upload NPI list blocks only: number of rows in the uploaded NPI list file.
includeAudienceIds
array of integers
Existing audience blocks only: included audience IDs.
excludeAudienceIds
array of integers
Existing audience blocks only: excluded audience IDs.
planLevelTargeting
object
Creative type, device, channel, and inventory targeting for the whole plan.
planLevelTargeting object properties
creativeTypes
object
Targeted creative types.
creativeTypes object properties
allCreativeTypesSelected
boolean
Whether all creative types are targeted.
creativeTypeIds
array of integers
Creative type IDs; empty when all creative types are targeted.
Supported values
11Image
13HTML
14Video
15Native
17Audio
isTvAutoBuying
boolean
Whether TV auto buying is enabled.
devices
object
Targeted devices.
devices object properties
allDeviceTypesSelected
boolean
Whether all device types are targeted.
deviceTypeIds
array of integers
Device type IDs; empty when all device types are targeted.
Supported values
20300001Mobile
20300002Desktop
20300003Connected TV
20300004Tablet
channels
object
Targeted channels.
channels object properties
allChannelTypesSelected
boolean
Whether all channels are targeted.
channelTypeIds
array of integers
Targeted channel type IDs; empty when all channels are targeted.
Supported values
11App
14CTV
13OTT
12Web
inventory
object
Targeted inventory.
inventory object properties
openExchanges
object
Targeted Open Exchange inventory: allExchangesSelected, exchangeIds, allIabCategoriesSelected, and iabCategoryIds.
inventoryGroup
object
Targeted inventory groups. Returned as an empty object when none are targeted; set it to null before sending the plan back to edit or publish it.
splitStrategy
array of objects
Split dimensions used to divide the plan into campaigns.
splitStrategy object properties
splitDimensionTypeId
integer
Split dimension ID.
Supported values
1Creative type
2NPI type
3Partner
4Device type
5Audience type
selectedValueIds
array of integers
Values the dimension is split by.
campaigns
array of objects
Proposed campaigns.
campaigns object properties
id
integer
Proposed campaign ID.
name
string
Campaign name.
campaignId
integer
ID of the campaign created when the plan is published; 0 until then.
strategy
string
Targeting dimensions the campaign was split by.
startTime
integer
Unix epoch start time in milliseconds.
endTime
integer
Unix epoch end time in milliseconds.
frequencyCap
integer
Frequency cap, copied from the plan.
frequencyCapTypeId
integer
Frequency cap type ID.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
minMediaCpm
number
Minimum media cost per mille (CPM).
mediaCpm
number
Media CPM.
maxMediaCpm
number
Maximum media CPM.
dataCpm
number
Data CPM, based on the selected data partners.
minBudget
number
Minimum campaign budget.
budget
number
Campaign budget.
maxBudget
number
Maximum campaign budget.
minReach
integer
Minimum campaign reach.
reach
integer
Campaign reach.
maxReach
integer
Maximum campaign reach.
minImpressions
integer
Minimum campaign impressions.
impressions
integer
Campaign impressions.
maxImpressions
integer
Maximum campaign impressions.
isAbm
boolean
Whether the campaign targets an ABM audience.
targeting
object
Campaign targeting.
targeting object properties
creativeTypeId
integer
Creative type ID.
Supported values
11Image
13HTML
14Video
15Native
17Audio
npiTypeId
integer
NPI type ID.
Supported values
3HCP
4NPI nurse
dataPartnerIds
array of integers
Data partner IDs.
Supported values
7Healthlink
8Data360
11Purple Lab
12RevOptimal
deviceTypeIds
array of integers
Device type IDs.
Supported values
20300001Mobile
20300002Desktop
20300003Connected TV
20300004Tablet
audienceTypeIds
array of integers
Audience type IDs.
Supported values
1Matched audience
2Segmented audience
4Geofarmed audience
5Contextual audience
9Account Based Marketing (ABM) audience
.
Response 200 (abbreviated)
{
"success": true,
"data": {
"id": 4512,
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"owId": 200001,
"createdAt": 1791800000000,
"updatedAt": 1791800000000,
"minBudget": null,
"budget": 8820.00,
"maxBudget": 8820.00,
"reach": 60000,
"maxReach": 60000,
"minImpressions": null,
"impressions": 360000,
"maxImpressions": 360000,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"statusId": 6,
"npiTypeIds": [3, 4],
"audienceBlocks": [ ... ],
"planLevelTargeting": {
"devices": { "deviceTypeIds": [20300001, 20300004], "allDeviceTypesSelected": false },
"creativeTypes": { "creativeTypeIds": [11, 14], "allCreativeTypesSelected": false, "isTvAutoBuying": false },
"channels": { "channelTypeIds": [], "allChannelTypesSelected": true },
"inventory": {
"openExchanges": { "exchangeIds": [], "allExchangesSelected": true, "iabCategoryIds": [], "allIabCategoriesSelected": true },
"inventoryGroup": { "inventoryGroupIds": [], "allInventoryGroupsSelected": false }
}
},
"splitStrategy": [
{ "splitDimensionTypeId": 1, "selectedValueIds": [11, 14] },
{ "splitDimensionTypeId": 2, "selectedValueIds": [3, 4] }
],
"campaigns": [
{
"id": 90001,
"name": "Image - Physicians",
"startTime": 1793505600000,
"endTime": 1796101199000,
"budget": 2331.00,
"impressions": 126000,
"reach": 42000,
"targeting": {
"dataPartnerIds": [7, 8],
"creativeTypeId": 11,
"deviceTypeIds": [20300001, 20300004],
"npiTypeId": 3,
"audienceTypeIds": [1]
},
"campaignId": 0
},
...
],
"ioId": 0
}
}
More responses
Response 403
{
"success": false,
"errorObjects": [
{
"error": "Plan with plan id 4512 does not exist"
}
]
}
Response 422
{
"success": false,
"errorObjects": [
{
"error": "Invalid Plan Id",
"field": "planId"
}
]
}

Step 5: Edit the plan​

PUT

Update the plan before publishing it. This step is optional. Send the full plan; the saved plan is replaced with the request body. Editing doesn't change the plan's status.

To edit, get the plan with Step 4, change the fields you need, and send it back.

The request schema is the same as Step 3, except for the fields in the table below.

warning

The statusId in the request must equal the plan's current status.

Plans in Processing (5) or IO Created (7) status can't be edited.

Path parameters
planId
integer required
Plan ID.
Request schema
id
integer required
Plan ID; must be the same as the planId path parameter.
statusId
integer required
The plan's current status ID from Step 4. Send it back unchanged.
minBudget
number
Minimum plan budget, from Step 2. Required for Ready plans: Step 4 returns it as null, and a null value returns a generic 500 error. Draft plans accept null.
minImpressions
integer
Minimum plan impressions, from Step 2. Required for Ready plans: Step 4 returns it as null, and a null value returns a generic 500 error. Draft plans accept null.
frequencyCap
integer required
Frequency cap, 1 to 99. Every campaign uses the plan's frequency cap, so change it here rather than in campaigns.
frequencyCapTypeId
integer required
Frequency cap type ID. Every campaign uses the plan's frequency cap type, so change it here rather than in campaigns.
Supported values
1Day(s)
2Week(s)
3Month(s)
4Campaign duration
planLevelTargeting
object required
Creative type, device, channel, and inventory targeting for the whole plan.
planLevelTargeting object properties
inventory
object required
Inventory to target.
inventory object properties
inventoryGroup
object
Send null unless you target inventory groups. Step 4 returns an empty inventory group object, which fails with Invalid inventory groups selected.
campaigns
array of objects required
Proposed campaigns. Each edit re-creates the campaigns with new id values, so don't store those IDs; publishing does the same. The frequencyCap and frequencyCapTypeId values in each campaign are ignored.
Request sample (abbreviated)
{
"id": 4512,
"statusId": 6,
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"minBudget": 98.00,
"budget": 8820.00,
"maxBudget": 8820.00,
"minImpressions": 4000,
"impressions": 360000,
"maxImpressions": 360000,
"frequencyCap": 5,
"frequencyCapTypeId": 2,
"npiTypeIds": [3, 4],
"audienceBlocks": [ ... ],
"planLevelTargeting": {
"devices": { ... },
"creativeTypes": { ... },
"channels": { ... },
"inventory": {
"openExchanges": { ... },
"inventoryGroup": null
}
},
"splitStrategy": [ ... ],
"campaigns": [ ... ]
}
Response 200
{
"success": true,
"data": {
"message": "Q4 Cardiology Awareness updated successfully",
"id": 4512
}
}
More responses
Response 422
{
"success": false,
"errorObjects": [
{
"error": "Proposal cannot be edited in its current status."
}
]
}

Step 6: Publish the IO and campaigns​

POST

Publish the plan to create an IO and campaigns. Send the full plan with its id and current statusId, as in Step 5. Publishing saves the request body first using the same checks as an edit, so the status echo rule applies here too.

The request returns immediately and the plan moves to Processing (5) while the audiences, IO, and campaigns are created in the background. When publishing finishes, the plan moves to IO Created (7) and its ioId is set. If publishing fails, the plan moves to Failed (4) and you can publish it again. The response doesn't include the IO ID: use Step 4 to check the result. Publishing can take more than a minute. It has finished successfully when statusId is 7, ioId is greater than 0, and every campaign's campaignId is greater than 0.

The campaigns are created as drafts. They don't run until creatives are attached and the campaigns are approved.

The request schema is the same as Step 5, except for the fields in the table below.

danger

Publishing is a one-way step. A published plan can't be returned to Ready, and calls that require a Ready, Failed, or Expired plan, such as editing, no longer work for it. Manage the generated IO and campaigns with the Campaign API.

Request schema
id
integer required
Plan ID from Step 3.
statusId
integer required
The plan's current status ID from Step 4.
Request sample (abbreviated)
{
"id": 4512,
"statusId": 6,
"name": "Q4 Cardiology Awareness",
"startTime": 1793505600000,
"endTime": 1796101199000,
"timezoneId": 29,
"budgetTypeId": 1,
"minBudget": 98.00,
"budget": 8820.00,
"maxBudget": 8820.00,
"minImpressions": 4000,
"impressions": 360000,
"maxImpressions": 360000,
"frequencyCap": 3,
"frequencyCapTypeId": 1,
"npiTypeIds": [3, 4],
"audienceBlocks": [ ... ],
"planLevelTargeting": {
"devices": { ... },
"creativeTypes": { ... },
"channels": { ... },
"inventory": {
"openExchanges": { ... },
"inventoryGroup": null
}
},
"splitStrategy": [ ... ],
"campaigns": [ ... ]
}
Response 200
{
"success": true,
"data": {
"message": "Campaign generation is in progress"
}
}
More responses
Response 422
{
"success": false,
"errorObjects": [
{
"error": "Proposal cannot be edited in its current status."
}
]
}

Step 7: Download the plan​

POST

Download the plan as a spreadsheet or PDF to share. This step is optional. The response contains a temporary download link.

Plans in Ready (6), Processing (5), IO Created (7), or Failed (4) status can be downloaded. Draft and expired plans can't.

Request schema
planId
integer required
Plan ID.
fileTypeId
integer required
File type ID.
Supported values
1Excel
3PDF
.
Response properties
downloadUrl
string
Temporary link to the generated file.
Request sample
{
"planId": 4512,
"fileTypeId": 1
}
Response 200
{
"success": true,
"data": {
"downloadUrl": "https://example-bucket.s3.amazonaws.com/Q4_Cardiology_Awareness_1791800000000.xlsx"
}
}
More responses
Response 422
{
"success": false,
"errorObjects": [
{
"error": "Invalid file type to download HCP Plan"
}
]
}
Have a question?
Was this page helpful?