Upload a Matched audience
Upload a Matched audience with this in-depth tutorial using IQM's API.
Get started uploading a Matched audience with the following endpoints:
POSTPOST
POST
GET
About IQM Matched audience
The Audience API allows you to upload an audience for matching in XLSX or CSV format. Once uploaded and processed, the Matched audience can be used for advertising campaign targeting.
More resources
- Matched audience Help Center article
- Audience API guidelines
Before you begin
To upload a Matched audience, the following are required:
- An account on the IQM platform
- See Getting started section to create an account and request a Client ID and Client Secret
- CSV or XLSX file for matching
File requirements for audience matching:
- CSV or XLSX file for audience matching with maximum 1GB or 5M records
- Without Voter ID / Email / Phone / Address in the file
- One of the following system field combinations is required for matching
- First Name, Last Name, Zip, State
- Last Name, Street Address, Zip, State
- Street Address, Zip, State
- Other fields are optional and can be added along with the above fields
- One of the following system field combinations is required for matching
- With Voter ID / Email / Phone / Address in the file
- Only one of these fields is required - Voter ID or Email or Phone, or Address. The preferred format for full address is Street, City, Zip, and State
- Other fields are optional and can be added along with one of the above fields
Upload a Matched audience using the IQM API
This tutorial covers how to create a Matched audience.
The minimum requirements to perform this task are: logging in with authentication credentials, selecting columns for matching, and uploading an audience. Once these steps are accomplished, more can be learned about IQM's API through the guidelines pages.
- Log in
- Optional if you have already logged in and have a token
- Get audience request properties
- Optional if you already know desired/supported columns
- Upload a Matched audience
- Upload the audience with parameters from the previous steps
- Check audience status
- A Matched audience requires processing and approval before it can be used for targeting
Authentication
Use the following header parameters for all requests after logging in:
| Headers | |
|---|---|
Authentication string required | Authentication bearer token See Sign up and authenticate |
X-IAA-OW-ID integer required | Organization Workspace ID Header |
Step 1: Log in
POSTTo log in, the Authentication: Basic header is required. The Login API returns an OAuth-compliant response with 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 | |
|---|---|
Authentication string required | Authentication bearer token See Sign up and authenticate |
| Request schema | |
|---|---|
grant_type string required | password for login 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."
}
]
}
Step 2: Get audience request properties
GETGET
GET
GET
GET
To upload a Matched audience, you need to gather some information about your audience and file to fill in the required parameters for the upload endpoint. These include:
| Parameter | Description |
|---|---|
| Audience subtype ID Healthcare vertical | The Audience subtype ID for the Matched audience being uploaded. |
| Column IDs for matching | A list of Column IDs for matching which correspond to the columns in the file being uploaded. |
| Data format ID | The Data format ID corresponds to the type of identifiers being uploaded. |
| Data partner ID | The Data partner ID corresponds to the source of the data being uploaded and is used for reporting purposes. |
| Column combination ID Political vertical | The Column combination ID corresponds to the combination of columns being used for matching. |
- JSON
- TypeScript
{
"success": true,
"data": [
{
"id": 1,
"label": "Voter ID",
"key": "Voters_ID",
"order": 1,
"isSingleColumn": true
},
{
"id": 26,
"label": "NPI ID",
"key": "NPI_ID",
"order": 2,
"isSingleColumn": true
},
{
"id": 2,
"label": "Email",
"key": "Email",
"order": 3,
"isSingleColumn": true
},
{
"id": 3,
"label": "Phone",
"key": "Phone",
"order": 4,
"isSingleColumn": true
},
{
"id": 4,
"label": "Full Address",
"key": "Residence_FullAddress",
"order": 5,
"isSingleColumn": true
},
{
"id": 5,
"label": "First Name",
"key": "Voters_FirstName",
"order": 6,
"isSingleColumn": false
},
{
"id": 6,
"label": "Last Name",
"key": "Voters_LastName",
"order": 7,
"isSingleColumn": false
},
{
"id": 7,
"label": "Zip",
"key": "Residence_Addresses_Zip",
"order": 8,
"isSingleColumn": false
},
{
"id": 8,
"label": "State",
"key": "Residence_Addresses_State",
"order": 9,
"isSingleColumn": false
},
{
"id": 9,
"label": "Street Address",
"key": "Residence_Addresses_AddressLine",
"order": 10,
"isSingleColumn": false
},
{
"id": 10,
"label": "Full Name",
"key": "Voters_FullName",
"order": 11,
"isSingleColumn": false
},
{
"id": 11,
"label": "City",
"key": "Residence_Addresses_City",
"order": 12,
"isSingleColumn": false
},
{
"id": 12,
"label": "ZipPlus4",
"key": "Residence_Addresses_ZipPlus4",
"order": 13,
"isSingleColumn": false
},
{
"id": 13,
"label": "Age",
"key": "Voters_Age",
"order": 14,
"isSingleColumn": false
},
{
"id": 14,
"label": "Gender",
"key": "Voters_Gender",
"order": 15,
"isSingleColumn": false
},
{
"id": 15,
"label": "Ethnicity",
"key": "Ethnic_Description",
"order": 16,
"isSingleColumn": false
},
{
"id": 16,
"label": "Latitude",
"key": "Residence_Addresses_Latitude",
"order": 17,
"isSingleColumn": false
},
{
"id": 17,
"label": "Longitude",
"key": "Residence_Addresses_Longitude",
"order": 18,
"isSingleColumn": false
}
]
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
success: boolean;
data: {
id: number;
label: string;
key: string;
order: number;
isSingleColumn: boolean;
}[];
}
};
};
};
function getMatchedAudienceColumnList(): Promise < Responses > {
const options = {
method: 'POST',
url: 'https://api.iqm.com/api/v3/audience/static/column-list',
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}
Step 3: Upload a Matched audience
POSTCreate a Matched audience by uploading a file with user data. The metadata is sent as a JSON string in the audienceRequest form data field, and the file is uploaded as multipart/form-data in the file form data field.
| Request schema | |
|---|---|
audienceRequest form data required | Audience metadata details |
file multipart/form-data required | File to be uploaded |
audienceRequest properties
audienceName string | Audience name | |||||||
fileRowCount integer | Number of rows in the file | |||||||
fileColumnCount integer | Number of columns in the file | |||||||
audienceSubtypeId integer | Audience subtype ID | |||||||
columnMappings array | Array of column mapping objects | |||||||
| ||||||||
columnId integer | Column ID |
fileColumnName string | File column name |
dataFormatId integer | Data format ID |
dataPartnerId integer
columnCombinationId integer
audienceRequest sample object for Political Matched audience
{
"audienceName": "matched-audience-example-fs",
"fileRowCount": 5,
"fileColumnCount": 10,
"columnMappings": [
{
"columnId": 5,
"fileColumnName": "l2-voter-id",
"dataFormatId": null
},
{
"columnId": 6,
"fileColumnName": "email",
"dataFormatId": 1
}
],
"dataPartnerId": 2,
"columnCombinationId": 11
}
audienceRequest sample object for Healthcare Matched audience
{
"audienceName": "Revamped Healthcare Matched Audience 02",
"dataPartnerId": 7,
"audienceSubtypeId": 3,
"columnMappings": [
{
"columnId": 18,
"fileColumnName": "NPI_ID"
}
],
"fileRowCount": 19,
"fileColumnCount": 1,
"columnCombinationId": 14,
"consentGiven": true
}
POST /api/v3/audience/matched HTTP/1.1
Host: api.iqm.com
Authorization: Bearer 0ed52da8-24ab-44b1-bc88-7ea03a090d24
X-IAA-OW-ID: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="audienceRequest"
Content-Type: application/json
{"audienceName":"Healthcare Patient Audience 2025","dataPartnerId":7,"audienceSubtypeId":3,"columnCombinationId":14,"fileRowCount":1200,"fileColumnCount":3,"consentGiven":true,"columnMappings":[{"columnId":18,"fileColumnName":"NPI_ID"},{"columnId":19,"fileColumnName":"first_name"},{"columnId":20,"fileColumnName":"last_name"}]}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="patient-data.csv"
Content-Type: text/csv
[Binary CSV file data]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
{
"success": true,
"data": {
"matchedAudienceId": 12345,
"message": "Matched audience created successfully"
}
}
Step 4: Check audience status
GETBefore the audience can be used for campaign targeting it has to be processed and approved. Once the status is Ready, the audience can be targeted. Use the matchedAudienceId generated in the last step with this endpoint to get audience details.
For further information see Matched audience details.
| Path parameters | |
|---|---|
audienceId string required | Matched audience ID |
- JSON
- TypeScript
{
"statusCode": 200,
"responseObject": {
"id": 1,
"audienceName": "Sample audience name",
"existingColumnMatching": "{\"FirstName\":\"Voters_FirstName\",\"LastName\":\"Voters_LastName\",\"State\":\"Residence_Addresses_State\",\"Zip4\":\"Residence_Addresses_Zip\"}",
"metadata": "{\"voterIDColumn\":[],\"columns\":[\"Voter File VANID\",\"LastName\",\"FirstName\",\"MiddleName\",\"Suffix\",\"Address\",\"City\",\"State\",\"Zip5\",\"Zip4\",\"Sex\",\"Age\",\"Preferred Phone\",\"CD\",\"SD\",\"HD \"],\"fileName\":\"NYSD3DigitalUniverse.csv\",\"fileSize\":7856375,\"rows\":0}",
"rawS3URL": "",
"status": "Pending",
"matchRate": 57.88,
"minEcpm": 0,
"maxEcpm": 0,
"s3FileName": "MatchedAudienceSample.csv",
"included": 0,
"excluded": 0,
"createdDate": 1642843451,
"modifiedDate": 1642843884,
"organizationName": "Sample organization name",
"userName": "Sample user name",
"dataCost": 1.5,
"owId": 1,
"uowId": 1,
"rawS3URLError": "File not available currently, please check later",
"uniques": 52432,
"approvedRejectedByUserName": "Sample user name",
"approvedRejectedByUserEmail": "example@example.com",
"isApprovalAccess": true,
"isEditAccess": true
}
}
See TypeScript prerequisites page for usage.
import {
getInstance
} from "prerequisites"
const axios = getInstance();
interface Responses {
200: {
content: {
"application/json": {
statusCode: number;
responseObject: {
id: number;
audienceName: string;
existingColumnMatching: string;
metadata: string;
rawS3URL: string;
status: string;
matchRate: number;
minEcpm: number;
maxEcpm: number;
s3FileName: string;
included: number;
excluded: number;
createdDate: number;
modifiedDate: number;
organizationName: string;
userName: string;
dataCost: number;
owId: number;
uowId: number;
rawS3URLError: string;
uniques: number;
approvedRejectedByUserName: string;
approvedRejectedByUserEmail: string;
isApprovalAccess: boolean;
isEditAccess: boolean;
};
};
};
};
};
function getMatchedAudienceDetails(): Promise < Responses > {
const options = {
method: 'GET',
url: 'https://api.iqm.com/api/v3/audience/matched/{audienceId}',
params: {
path: {
audienceId: `number`,
}
}
};
return axios.request(options).then(({ data }: { data: Responses }) => data);
}