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:
POSTPOST
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:
- Targeting consistency: The split strategy must agree with the plan-level targeting when you save, edit, or publish the plan. See Step 1.
- Status echo: Every edit and publish request must include the plan's current statusId. See Step 5.
More resources
- Planner API guidelines
- Audience API guidelines
- Political Planner tutorial
- HCP Planner overview Help Center article
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
POSTTo 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. |
- JSON
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>'
{
"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
{
"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."
}
]
}
{
"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:
- Plan the audience and targeting
- Generate campaigns
- Create a plan
- Get plan details
- Edit the plan
- Optional
- Publish the IO and campaigns
- 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.
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.
| Method | ID | Required block fields | Audience type |
|---|---|---|---|
| Filter based | 1 | speciality, locations, dataPartners | Matched audience (1) |
| Upload NPI list | 2 | speciality, locations, dataPartners, and storagePathId from an uploaded NPI file | Matched audience (1) |
| Existing audience | 3 | includeAudienceIds and/or excludeAudienceIds, up to 14 in total. Don't send specialty, location, or data partner fields. | Taken from the selected audiences |
| Account based | 4 | speciality, 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": {
"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 dimension | splitDimensionTypeId | selectedValueIds must agree with | Rule | Campaign field |
|---|---|---|---|---|
| Creative type | 1 | planLevelTargeting.creativeTypes.creativeTypeIds | Exact match | targeting.creativeTypeId |
| NPI type | 2 | npiTypeIds | Subset | targeting.npiTypeId |
| Data partner | 3 | dataPartners[].id across all audience blocks | Subset | targeting.dataPartnerIds |
| Device type | 4 | planLevelTargeting.devices.deviceTypeIds | Subset | targeting.deviceTypeIds |
| Audience type | 5 | Audience types of all audience blocks | Subset | targeting.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.
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
POSTSend 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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
frequencyCap integer required | Frequency cap, 1 to 99. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
frequencyCapTypeId integer required | Frequency cap type ID. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
npiTypeIds array of integers required | NPI type IDs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceBlocks array of objects required | Audience blocks, at most one per audience selection method. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceSelectionMethodId integer required | Audience selection method ID. Account based blocks need additional account, health system, and title fields. | |||||||||||||||
speciality object | Specialties to target. Required for filter based, upload NPI list, and account based blocks. | |||||||||||||||
| ||||||||||||||||
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 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
dataPartners object properties
id integer required | Data partner ID. Account based blocks support only 7 and 12. |
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
includeAudienceIds array of integers
excludeAudienceIds array of integers
planLevelTargeting object required
planLevelTargeting object properties
creativeTypes object required | Creative types to target. | ||||||||||||||||
| |||||||||||||||||
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. |
isTvAutoBuying boolean | Whether TV auto buying is enabled; requires video creatives (14). |
devices object required
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. |
channels object required
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. |
inventory object required
inventory object properties
openExchanges object required | Open Exchange inventory to target. | |||||||||
| ||||||||||
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
splitStrategy array of objects required
splitStrategy object properties
splitDimensionTypeId integer required | Split dimension ID. Each dimension can appear once. |
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. | |||||||||||||||||||
| ||||||||||||||||||||
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. |
- JSON
- TypeScript
{
"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] }
]
}
{
"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]
}
},
...
]
}
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface HcpCampaign {
id: number | null;
name: string;
startTime: number;
endTime: number;
frequencyCap: number;
frequencyCapTypeId: number;
minMediaCpm: number;
mediaCpm: number;
maxMediaCpm: number;
dataCpm: number;
minBudget: number;
budget: number;
maxBudget: number;
minReach: number;
reach: number;
maxReach: number;
minImpressions: number;
impressions: number;
maxImpressions: number;
isAbm: boolean;
targeting: {
dataPartnerIds: number[];
creativeTypeId: number;
deviceTypeIds: number[];
npiTypeId: number;
audienceTypeIds: number[];
};
}
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
name: string;
startTime: number;
endTime: number;
timezoneId: number;
budgetTypeId: number;
minBudget: number;
budget: number;
maxBudget: number;
reach: number;
maxReach: number;
minImpressions: number;
impressions: number;
maxImpressions: number;
frequencyCap: number;
frequencyCapTypeId: number;
npiTypeIds: number[];
audienceBlocks: object[];
planLevelTargeting: object;
splitStrategy: {
splitDimensionTypeId: number;
selectedValueIds: number[];
}[];
campaigns: HcpCampaign[];
};
};
};
};
}
function generateHCPProposedCampaigns(): Promise<Responses> {
const options = {
method: 'POST',
url: 'https://api.iqm.com/api/v3/plan/hcp/generate-campaigns',
requestBody: {
content: {
"application/json": {
name: `string`,
startTime: `number`,
endTime: `number`,
timezoneId: `number`,
budgetTypeId: `number`,
frequencyCap: `number`,
frequencyCapTypeId: `number`,
npiTypeIds: `array of numbers`,
audienceBlocks: `array of objects`,
planLevelTargeting: `object`,
splitStrategy: `array of objects`,
}
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 3: Create a plan
POSTPOST
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
npiTypeIds array of integers required | NPI type IDs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceBlocks array of objects required | Audience blocks, at most one per audience selection method. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceSelectionMethodId integer required | Audience selection method ID. Account based blocks need additional account, health system, and title fields. | |||||||||||||||
speciality object | Specialties to target. Required for filter based, upload NPI list, and account based blocks. | |||||||||||||||
| ||||||||||||||||
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 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
dataPartners object properties
id integer required | Data partner ID. Account based blocks support only 7 and 12. |
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
includeAudienceIds array of integers
excludeAudienceIds array of integers
planLevelTargeting object required
planLevelTargeting object properties
creativeTypes object required | Creative types to target. | ||||||||||||||||
| |||||||||||||||||
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. |
isTvAutoBuying boolean | Whether TV auto buying is enabled; requires video creatives (14). |
devices object required
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. |
channels object required
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. |
inventory object required
inventory object properties
openExchanges object required | Open Exchange inventory to target. | |||||||||
| ||||||||||
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
splitStrategy array of objects required
splitStrategy object properties
splitDimensionTypeId integer required | Split dimension ID. Each dimension can appear once. |
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
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. | |||||||||||
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. | |||||||||||
| ||||||||||||
creativeTypeId integer required | Creative type ID. |
npiTypeId integer required | NPI type ID. |
dataPartnerIds array of integers required | Data partner IDs. |
deviceTypeIds array of integers required | Device type IDs. |
audienceTypeIds array of integers required | Audience type IDs. . |
- JSON
- TypeScript
{
"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] }
}
]
}
{
"success": true,
"data": {
"message": "Q4 Cardiology Awareness generated successfully",
"id": 4512
}
}
More responses
{
"success": false,
"errorObjects": [
{
"error": "Selected creative type IDs and split IDs do not match."
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
message: string;
id: number;
};
};
};
};
422: {
content: {
"application/json": {
success: boolean;
errorObjects: {
error: string;
}[];
};
};
};
}
function createProposal(): Promise<Responses> {
const options = {
method: 'POST',
url: 'https://api.iqm.com/api/v3/plan/hcp/proposal/add',
requestBody: {
content: {
"application/json": {
name: `string`,
startTime: `number`,
endTime: `number`,
timezoneId: `number`,
budgetTypeId: `number`,
minBudget: `number`,
budget: `number`,
maxBudget: `number`,
minImpressions: `number`,
impressions: `number`,
maxImpressions: `number`,
reach?: `number`,
maxReach?: `number`,
frequencyCap: `number`,
frequencyCapTypeId: `number`,
npiTypeIds: `array of numbers`,
audienceBlocks: `array of objects`,
planLevelTargeting: `object`,
splitStrategy: `array of objects`,
campaigns: `array of objects`,
}
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 4: Get plan details
GETUse 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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
npiTypeIds array of integers | NPI type IDs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceBlocks array of objects | Audience blocks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
audienceSelectionMethodId integer | Audience selection method ID. | |||||||||||||||
speciality object | Targeted specialties; null for existing audience blocks. | |||||||||||||||
| ||||||||||||||||
allSpecialitiesSelected boolean | Whether all specialties are targeted. |
specialityIds array of integers | Specialty IDs; empty when all specialties are targeted. |
locations object
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
dataPartners object properties
id integer | Data partner ID. |
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
storageFileName string
storageFileRows integer
includeAudienceIds array of integers
excludeAudienceIds array of integers
planLevelTargeting object
planLevelTargeting object properties
creativeTypes object | Targeted creative types. | |||||||
| ||||||||
allCreativeTypesSelected boolean | Whether all creative types are targeted. |
creativeTypeIds array of integers | Creative type IDs; empty when all creative types are targeted. |
isTvAutoBuying boolean | Whether TV auto buying is enabled. |
devices object
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. |
channels object
channels object properties
allChannelTypesSelected boolean | Whether all channels are targeted. |
channelTypeIds array of integers | Targeted channel type IDs; empty when all channels are targeted. |
inventory object
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
splitStrategy object properties
splitDimensionTypeId integer | Split dimension ID. |
selectedValueIds array of integers | Values the dimension is split by. |
campaigns array of objects
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. | |||||||||||
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. | |||||||||||
| ||||||||||||
creativeTypeId integer | Creative type ID. |
npiTypeId integer | NPI type ID. |
dataPartnerIds array of integers | Data partner IDs. |
deviceTypeIds array of integers | Device type IDs. |
audienceTypeIds array of integers | Audience type IDs. . |
- JSON
- TypeScript
{
"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
{
"success": false,
"errorObjects": [
{
"error": "Plan with plan id 4512 does not exist"
}
]
}
{
"success": false,
"errorObjects": [
{
"error": "Invalid Plan Id",
"field": "planId"
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
id: number;
name: string;
startTime: number;
endTime: number;
timezoneId: number;
budgetTypeId: number;
owId: number;
createdAt: number;
updatedAt: number;
minBudget: number | null;
budget: number;
maxBudget: number;
reach: number;
maxReach: number;
minImpressions: number | null;
impressions: number;
maxImpressions: number;
frequencyCap: number;
frequencyCapTypeId: number;
statusId: number;
npiTypeIds: number[];
audienceBlocks: object[];
planLevelTargeting: object;
splitStrategy: {
splitDimensionTypeId: number;
selectedValueIds: number[];
}[];
campaigns: object[];
ioId: number;
};
};
};
};
}
function getHcpPlanById(): Promise<Responses> {
const options = {
method: 'GET',
url: 'https://api.iqm.com/api/v3/plan/hcp/plans/{planId}',
params: {
path: {
planId: `number`,
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 5: Edit the plan
PUTUpdate 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.
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. | ||||||||
planLevelTargeting object required | Creative type, device, channel, and inventory targeting for the whole plan. | ||||||||
| |||||||||
inventory object required | Inventory to target. | |||
| ||||
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
- JSON
- TypeScript
{
"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": [ ... ]
}
{
"success": true,
"data": {
"message": "Q4 Cardiology Awareness updated successfully",
"id": 4512
}
}
More responses
{
"success": false,
"errorObjects": [
{
"error": "Proposal cannot be edited in its current status."
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
message: string;
id: number;
};
};
};
};
422: {
content: {
"application/json": {
success: boolean;
errorObjects: {
error: string;
}[];
};
};
};
}
function editProposal(): Promise<Responses> {
const options = {
method: 'PUT',
url: 'https://api.iqm.com/api/v3/plan/hcp/proposal/{planId}',
params: {
path: {
planId: `number`,
}
},
requestBody: {
content: {
"application/json": {
id: `number`,
statusId: `number`,
// ...all other fields from Step 3
}
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 6: Publish the IO and campaigns
POSTPublish 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.
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. |
- JSON
- TypeScript
{
"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": [ ... ]
}
{
"success": true,
"data": {
"message": "Campaign generation is in progress"
}
}
More responses
{
"success": false,
"errorObjects": [
{
"error": "Proposal cannot be edited in its current status."
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
message: string;
};
};
};
};
422: {
content: {
"application/json": {
success: boolean;
errorObjects: {
error: string;
}[];
};
};
};
}
function publishCampaigns(): Promise<Responses> {
const options = {
method: 'POST',
url: 'https://api.iqm.com/api/v3/plan/hcp/campaigns/publish',
requestBody: {
content: {
"application/json": {
id: `number`,
statusId: `number`,
// ...all other fields from Step 3
}
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 7: Download the plan
POSTDownload 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. . |
Response properties
downloadUrl string | Temporary link to the generated file. |
- JSON
- TypeScript
{
"planId": 4512,
"fileTypeId": 1
}
{
"success": true,
"data": {
"downloadUrl": "https://example-bucket.s3.amazonaws.com/Q4_Cardiology_Awareness_1791800000000.xlsx"
}
}
More responses
{
"success": false,
"errorObjects": [
{
"error": "Invalid file type to download HCP Plan"
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
success: boolean;
data: {
downloadUrl: string;
};
};
};
};
422: {
content: {
"application/json": {
success: boolean;
errorObjects: {
error: string;
}[];
};
};
};
}
function downloadPlan(): Promise<Responses> {
const options = {
method: 'POST',
url: 'https://api.iqm.com/api/v3/plan/hcp/plan/download',
requestBody: {
content: {
"application/json": {
planId: `number`,
fileTypeId: `number`,
}
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}