Below you will find all routes and parameters of the Masslytics API.
If you do not have an API token yet, see API Access.
All routes are relative to the base URL:
https://app.masslytics.io/api
Every request must contain your API token as a bearer token. Send and accept JSON:
curl https://app.masslytics.io/api/brands \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
A token belongs to a user, and has access to the same brands as that user has in the Masslytics interface.
You can verify your token with GET /user, which returns the user the token belongs to.
Most routes refer to a brand by its identifier. This is the code that is also part of your tag, for example ML-123456.
| Status | Meaning |
|---|---|
400 |
A query parameter has an invalid value. |
401 |
The API token is missing or invalid. |
403 |
Your user has no access to this brand or item. |
404 |
The brand or item does not exist. |
422 |
The request body did not pass validation. The response lists the errors per field. |
Routes that return results accept the same two query parameters:
| Parameter | Description |
|---|---|
startDate |
First day of the period, for example 2026-10-13. Defaults to 7 days before yesterday. |
endDate |
Last day of the period. Defaults to yesterday. |
Results are calculated overnight, so the most recent day available is always yesterday. A later endDate is moved back to yesterday.
Broadcast times in responses are shown in the timezone of the user the token belongs to, in the format YYYY-MM-DD HH:MM:SS.
| Method | Route | Description |
|---|---|---|
GET |
/brands |
List all brands you have access to. |
GET |
/brands/{identifier} |
Show one brand. |
POST |
/brands |
Create a brand. |
PUT |
/brands/{identifier} |
Update a brand. |
DELETE |
/brands/{identifier} |
Delete a brand. Returns 204. |
Body parameters for creating and updating
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Name of the brand, at most 255 characters. |
base_url |
string | No | Base URL of the website, for example https://example.com. |
disabled |
boolean | No | Disables the brand. Defaults to false. |
advertiser_id |
integer | No | Only when creating: the advertiser the brand belongs to. Defaults to your own organization. |
Response
{
"id": 12,
"name": "Example",
"identifier": "ML-123456",
"base_url": "https://example.com",
"disabled": false,
"install_check": "success",
"last_visitor_at": "2026-10-13T10:15:00.000000Z",
"script_tag": "<script>...</script>"
}
The script_tag field contains the tag that must be placed on the website. See Installing the pixel.
| Method | Route | Description |
|---|---|---|
GET |
/installCheck/{identifier} |
Check whether the tag of a brand is installed. |
Response
{
"status": "success",
"last_visitor_at": "2026-10-13T10:15:00.000000Z"
}
| Status | Meaning |
|---|---|
failed |
No data has been received for this brand. |
success_no_calculation |
Data is coming in, but no results have been calculated yet. |
success_no_baseurl |
Data is coming in, but from a different URL than the base URL of the brand. |
success |
The tag is installed and results are available. |
{info} Every status that starts with
successmeans the tag is installed. Check for the prefix instead of the exact value.
A conversion URL is a piece of text. Every page view with a URL that contains this text counts as a conversion.
| Method | Route | Description |
|---|---|---|
GET |
/brands/{identifier}/conversionUrls |
List the conversion URLs of a brand. |
POST |
/brands/{identifier}/conversionUrls |
Add a conversion URL. |
PUT |
/brands/{identifier}/conversionUrls/{id} |
Update a conversion URL. |
DELETE |
/brands/{identifier}/conversionUrls/{id} |
Delete a conversion URL. Returns 204. |
GET |
/brands/{identifier}/conversionUrls/aiSuggestions |
List suggested conversion URLs for a brand. |
Body parameters for creating and updating
| Parameter | Type | Required | Description |
|---|---|---|---|
string |
string | Yes | The text a URL must contain, for example /thank-you. At most 255 characters. |
A broadcast is one moment at which your advertisement aired.
| Method | Route | Description |
|---|---|---|
GET |
/broadcasts |
List the broadcasts of all brands you have access to. |
GET |
/broadcasts/{id} |
Show one broadcast. |
POST |
/broadcasts |
Create a broadcast. |
PUT |
/broadcasts/{id} |
Update a broadcast. |
DELETE |
/broadcasts/{id} |
Delete a broadcast. Returns 204. |
POST |
/broadcasts/bulkStore |
Create or update several broadcasts at once. |
POST |
/broadcasts/bulkDestroy |
Delete several broadcasts at once. Returns 204. |
Query parameters for listing
| Parameter | Description |
|---|---|
dateRange |
today, week, month or custom. Without this parameter all broadcasts are returned. |
startDate |
Start of the period. Required when dateRange is custom. |
endDate |
End of the period. Required when dateRange is custom. |
Body parameters for creating and updating
| Parameter | Type | Required | Description |
|---|---|---|---|
brand_identifier |
string | Yes | Identifier of the brand. |
time |
datetime | Yes | Moment the advertisement aired, for example 2026-10-13 14:30:00. |
timezone |
string | Yes | Timezone of time, for example Europe/Amsterdam. |
name |
string | No | Name of the commercial. Needed for AB-testing. |
channel |
string | No | Name of the channel. Needed for channel optimization. |
impact_type |
string | No | What the impact score measures: grp, impressions or price. |
impact_score |
number | No | The reach or price of this broadcast. |
external_id |
string | No | The ID of this broadcast in your own system. |
Response
{
"id": 3401,
"brand_id": 12,
"name": "Spring commercial",
"channel": "Radio One",
"time": "2026-10-13 14:30:00",
"end": "2026-10-13 14:35:00",
"impact_type": "grp",
"impact_score": 2.4,
"external_id": "A-1001"
}
POST /broadcasts/bulkStore accepts a broadcasts array. Every item has the same parameters as a single broadcast, except that timezone is optional and defaults to UTC.
{
"broadcasts": [
{
"brand_identifier": "ML-123456",
"time": "2026-10-13 14:30:00",
"timezone": "Europe/Amsterdam",
"name": "Spring commercial",
"channel": "Radio One",
"external_id": "A-1001"
}
]
}
If a broadcast with the same external_id already exists, it is updated instead of created again. This makes it safe to send a revised schedule more than once.
The response is the list of broadcasts that were created or updated.
{info} Items that do not pass validation are skipped without an error. Compare the number of broadcasts in the response to the number you sent.
POST /broadcasts/bulkDestroy accepts an ids array with the IDs of the broadcasts to delete.
A campaign is a period in which your advertisements ran. See Managing Campaigns.
| Method | Route | Description |
|---|---|---|
GET |
/campaigns |
List the campaigns of all brands you have access to. |
GET |
/campaigns/{uuid} |
Show one campaign. |
POST |
/campaigns |
Create a campaign. |
PUT |
/campaigns/{uuid} |
Update a campaign. |
DELETE |
/campaigns/{uuid} |
Delete a campaign. Returns 204. |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Name of the campaign, at most 255 characters. |
start |
datetime | Yes | Start of the campaign. |
end |
datetime | Yes | End of the campaign. Must be after start. |
uuid |
string | When creating | A unique UUID that you generate yourself. You use it to refer to the campaign afterwards. |
brand_identifier |
string | When creating | Identifier of the brand. |
| Method | Route | Description |
|---|---|---|
GET |
/results/{identifier}/daily |
Results per day. |
GET |
/results/{identifier}/hourly |
Results per hour. |
GET |
/results/{identifier} |
Results per day, or per broadcast when type is instant. |
Query parameters
| Parameter | Description |
|---|---|
startDate |
See Dates and timezones. |
endDate |
See Dates and timezones. |
type |
The attribution method: extended (default) or instant. |
Response
The response is an object with one entry per day (2026-10-13) or per hour (2026-10-13 14:00:00):
{
"2026-10-13": {
"broadcasts": 12,
"visitors_in": 340,
"visitors_out": 5120,
"total_visitors": 5460,
"average_in": 5.6,
"average_out": 3.7,
"uptick": 114,
"regular_visitors": 5346,
"conversions_total": 41,
"conversions": 3,
"conversions_out": 38,
"conversions_ratio": 0.07
}
}
| Field | Description |
|---|---|
broadcasts |
Number of broadcasts. |
visitors_in |
Website visitors during the time windows of your broadcasts. |
visitors_out |
Website visitors outside those time windows. |
total_visitors |
All website visitors. |
average_in |
Average visitors per minute during broadcasts. |
average_out |
Average visitors per minute outside broadcasts. |
uptick |
Extra website visitors caused by your broadcasts. |
regular_visitors |
Website visitors that are not attributed to your broadcasts. |
conversions_total |
All conversions. |
conversions |
Conversions attributed to your broadcasts. |
conversions_out |
Conversions that are not attributed to your broadcasts. |
When you request GET /results/{identifier} with type=instant, the response has one entry per broadcast. Each entry also contains a broadcast field with the broadcast itself.
| Method | Route | Description |
|---|---|---|
GET |
/topPages/{identifier} |
The 10 most visited pages in the period. |
Accepts startDate and endDate.
[
{
"domain": "https://example.com",
"path": "/pricing",
"total": 812
}
]
| Method | Route | Description |
|---|---|---|
GET |
/channel-optimization/{identifier}/table |
Performance per channel over the whole period. |
GET |
/channel-optimization/{identifier}/graph |
Performance per channel per day. |
Both accept startDate and endDate.
Response of the table
{
"impactTypes": ["grp"],
"showImpactScoreRatio": true,
"tableData": [
{
"channel": "Radio One",
"visitors": 214.5,
"broadcasts": 38,
"impact_score": 91.2,
"visitors_per_broadcast": 5.64,
"visitors_per_impact_score": 2.35
}
]
}
The channels are sorted from best to worst performing. visitors_per_impact_score is only meaningful when all broadcasts in the period use the same impact type, which is the case when showImpactScoreRatio is true.
The graph route returns the same fields in graphData, with a data list per channel that holds one entry per day.
| Method | Route | Description |
|---|---|---|
POST |
/creative-studio/{identifier}/ab-test |
Compare the impact of two commercials. |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
startDate |
date | Yes | First day of the period. |
endDate |
date | Yes | Last day of the period. |
commercialA |
string | Yes | Name of the first commercial, as used in name of your broadcasts. |
commercialB |
string | Yes | Name of the second commercial. |
attributionMethod |
string | Yes | extended or instant. |
Response
{
"commercial_names": { "commercialA": "Spring", "commercialB": "Summer" },
"uptick_sums": { "commercialA": 120, "commercialB": 96 },
"average_upticks": { "commercialA": 4.8, "commercialB": 3.2 },
"num_broadcasts": { "commercialA": 25, "commercialB": 30 },
"winner": "Spring",
"winner_label": "A",
"percentage_difference": 50
}
winner_label is A, B or DRAW. The winner is the commercial with the highest average number of extra visitors per broadcast.
| Method | Route | Description |
|---|---|---|
GET |
/roi/{identifier}/onTraffic |
Regular visitors and extra visitors per day. |
GET |
/roi/{identifier}/returnOnConversions |
Regular conversions and mass media conversions per day. |
GET |
/roi/{identifier}/reachToConversions |
Conversions and summed impact scores per day. |
GET |
/roi/{identifier}/mediaPressure |
Broadcasts, reach and assumed conversions per channel. |
Query parameters
| Parameter | Description |
|---|---|
startDate |
See Dates and timezones. |
endDate |
See Dates and timezones. |
attributionMethod |
extended or instant. When left out, the method last used by the user is applied. |
The first three routes return a dates list, with lists of values in the same order:
| Route | Fields |
|---|---|
onTraffic |
dates, regularVisitors, uptick |
returnOnConversions |
dates, regularConversions, massMediaConversions |
reachToConversions |
dates, conversions, impactScores (one list per impact type) |
{
"dates": ["2026-10-12", "2026-10-13"],
"regularVisitors": [5346, 5102],
"uptick": [114, 98]
}
mediaPressure returns one row per channel in tableData. Reach is based on broadcasts with impact type grp.
{
"tableData": [
{
"source": "Radio One",
"broadcasts": 38,
"reach": 91.2,
"avg_reach": 2.4,
"assumed_conversions": 11.5
}
]
}
| Method | Route | Description |
|---|---|---|
GET |
/indirectImpact/{identifier} |
Compare a campaign period to a period without a campaign. |
Query parameters
| Parameter | Description |
|---|---|
brand |
The id of the brand. |
campaign |
The id of the campaign. Defaults to the most recent campaign of the brand. |
compare |
Start date of the period to compare with. Defaults to a period of the same length right before the campaign. |
Response
{
"indirectVisitors": 1840,
"indirectVisitorPercentage": 12.4,
"indirectConversions": 22,
"indirectConversionPercentage": 9.1,
"conclusion": "positive"
}
conclusion is positive when there were more regular visitors than expected during the campaign, neutral when there were not, and invalid when there is no campaign or no period to compare with.