Endpoint
POST /msearch/viewcast
Search and filter out-of-home advertising inventory with Viewcast measurements. This endpoint queries the inventory Elasticsearch index, returning detailed spot-level information including media characteristics, location data, operator details, and display attributes. Results are limited to inventory that has Viewcast measurement data available.
Type
POST
Limitations
- Rate Limit: Maximum 20 API requests per minute per API Key
- Default Page Size: 50 results per page
- Maximum Results: Pagination is limited to 10,000 total records (
page×page_sizecannot exceed 10,000) - Filter Values: Each filter accepts a single value; array values are not supported
- Filter Combination: Multiple filters are combined using AND logic
Request Parameters
The request body should be a JSON object containing the search criteria and configuration options.
Request Structure:
- Optional
filter: Object containing search criteria and filters (also acceptsfilters)fieldSet: Array of strings - Limits which fields are returned in the response (see Field Selection below)pagination: Object with page and page_size settings (default:{page: 1, page_size: 50})sort: Object with field and order settings (default:{field: "id", order: "asc"})
Note: If no filter is provided or the request body is empty (
{}), all inventory with Viewcast measurements will be returned (currently ~793,000 records).
Filter Options:
The filter object supports the following search criteria:
Location
dma_name: String - Filter by Designated Market Area name (e.g., "New York, NY", "Chicago, IL")state: String - Filter by state abbreviation (e.g., "NY", "CA", "IL")zip_code: String - Filter by ZIP code (e.g., "10019", "60606")cbsa_name: String - Filter by CBSA name (e.g., "New York-Newark-Jersey City, NY-NJ-PA")county_name: String - Filter by county name (e.g., "New York County")primary_artery: String - Filter by road or intersection name; supports partial matching (e.g., "Broadway")
Geographic
geo_distance: Object - Filter by radius from a point. Requireslat(number),lon(number), anddistance(string with unit, e.g., "1km", "5mi")geo_bounding_box: Object - Filter by geographic bounding box. Requirestop_leftandbottom_rightobjects, each withlatandlon
Media & Display
media_type_name: String - Filter by media type (e.g., "Bulletin", "Poster", "Panel", "Display", "Junior Poster", "Murals")media_name: String - Filter by operator's media name (e.g., "Digital Bulletins", "Transit Shelters")construction_type_name: String - Filter by construction/structure type (e.g., "Freestanding", "Furniture", "Exterior Wall", "Interior Wall")illumination_type_name: String - Filter by illumination type (e.g., "Backlit", "Frontlit")digital: Boolean - Filter by digital (true) or static (false) displaysfull_motion: Boolean - Filter by full motion video capabilityinteractive: Boolean - Filter by interactive capabilityrotating: Boolean - Filter by rotating displayaudio: Boolean - Filter by audio capability
Spot ID Range
id_min: Integer - Filter by minimum spot ID (inclusive)id_max: Integer - Filter by maximum spot ID (inclusive)
Text Search
search: String - Multi-field text search across DMA name, CBSA name, county name, primary artery, and media name
Pagination Options:
page: Number - Page number (1-based, default: 1)page_size: Number - Number of results per page (default: 50)
Sorting Options:
field: String - Field to sort by (default: "id")order: String - Sort direction "asc" or "desc" (default: "asc")
Field Selection
The fieldSet parameter allows you to request only specific fields in the response, reducing payload size. Provide an array of field paths using dot-notation to select nested fields.
Note: Field selection operates on the underlying Elasticsearch field names. To include the spot ID in the response, use
"id"(it will be returned asspot_idafter field renaming). WhenfieldSetis not provided, all default fields are returned. Thestatusandtotalresponse fields are always included regardless offieldSet.
Example field paths:
"id"- Spot ID (returned asspot_idin response)"digital"- Digital display flag"media_name"- Operator's media name"audio","full_motion","interactive","rotating","partial_motion"- Media capability flags"location.state"- State abbreviation"location.dma_name"- DMA name"location.geometry"- GeoJSON coordinates"media_type.name"- Media type classification"construction.construction_type.name"- Construction type"illumination_type.name"- Illumination type"classification_type.name"- Classification type (Roadside/Place Based)"placement_type.name"- Placement type"status_type.name"- Status type"representations"- Full operator/representation data"layouts"- Full layout, face, and spot detail
Responses
200 OK: Successfully retrieved search results400 Bad Request: Invalid filter parameters (e.g., unsupported array values)500 Internal Server Error: Server-side search error
Response Structure:
status: String - "success" on successful querytotal: Number - Total count of matching inventory recordsresults: Array of inventory objects (see Response Fields below)
Response Fields
Each inventory result contains:
Top-Level Fields:
spot_id: Integer - Geopath Spot ID (renamed fromidin the underlying index)digital: Boolean - Whether the display is digitalaudio: Boolean - Audio capabilityfull_motion: Boolean - Full motion video supportpartial_motion: Boolean - Partial motion supportinteractive: Boolean - Interactive capabilityrotating: Boolean - Whether spots rotate on the facemedia_name: String - Operator's media name (e.g., "Digital Bulletins", "Transit Shelters (TSA)")
Illumination:
illumination_type: Object withname(e.g., "Backlit", "Frontlit")illumination_start_time: String - Start time (HH:MM:SS)illumination_end_time: String - End time (HH:MM:SS)
Classification:
classification_type: Object withname("Roadside" or "Place Based")construction: Object containingconstruction_typewithidandnamemedia_type: Object withname(e.g., "Bulletin", "Poster", "Panel")placement_type: Object withname(e.g., "Set Back", "Curbside", "Dining Area")status_type: Object withname(e.g., "Published - Measured")
Location:
location: Object containing:state: String - State abbreviationcounty_id: String - County FIPS codecounty_name: String - County namedma_id: String - DMA identifierdma_name: String - DMA namecbsa_code: String - CBSA codecbsa_name: String - CBSA namezip_code: String - ZIP codeprimary_artery: String - Primary road or intersection descriptiongeometry: GeoJSON Point withcoordinates[longitude, latitude] andtypeorientation: Number - Face orientation in degreesplace_types: Object withname(e.g., "Central Business District", "Suburban")
Layouts (Face & Spot Detail):
layouts: Array of layout objects, each containing:id: Integer - Layout/frame IDfaces: Array of face objects with:id: Integer - Face IDwidth: Integer - Face width (inches)height: Integer - Face height (inches)spots: Array of spot objects with:id: Integer - Spot IDplant_spot_id: String - Operator's internal spot identifierspot_share_of_voice: String - Share of voice as decimalspot_length: Integer - Spot length in seconds (for digital)measures: Array with viewcast vintage date (e.g.,{"viewcast": "20260308"})- Media attribute booleans:
rotating,audio,full_motion,partial_motion,interactive
Operators:
representations: Nested array containing account objects with:account.name: String - Division/local account nameaccount.parent_account_name: String - Parent operator name (e.g., "Clear Channel", "JCDecaux")representation_type.name: String - Representation type (e.g., "Own")
Place:
place: Object withplace_idandplace_name(may be empty if no associated place)
Example Request - All Inventory (No Filter)
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Filter by DMA
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"dma_name": "New York, NY"
},
"pagination": {
"page": 1,
"page_size": 25
}
}'Example Request - Combined Filters
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"state": "NY",
"media_type_name": "Bulletin",
"digital": true
},
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Filter by ZIP Code and Construction Type
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"zip_code": "10019",
"construction_type_name": "Freestanding"
},
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Geographic Radius Search
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"geo_distance": {
"lat": 40.761,
"lon": -73.984,
"distance": "1km"
}
},
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Geographic Bounding Box
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"geo_bounding_box": {
"top_left": {"lat": 40.77, "lon": -73.99},
"bottom_right": {"lat": 40.75, "lon": -73.97}
}
},
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Text Search
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"search": "Broadway"
},
"pagination": {
"page": 1,
"page_size": 10
}
}'Example Request - Field Selection with fieldSet
curl --location 'https://intermx-test.apigee.net/int/v1/msearch/viewcast' \
--header 'Content-Type: application/json' \
--header 'apikey: {YOUR API KEY HERE}' \
--data '{
"filter": {
"state": "NY",
"media_type_name": "Bulletin",
"digital": true
},
"fieldSet": [
"id",
"digital",
"media_name",
"location.state",
"location.dma_name",
"location.geometry",
"media_type.name",
"construction.construction_type.name",
"representations"
],
"pagination": {
"page": 1,
"page_size": 10
}
}'Example fieldSet Response:
{
"status": "success",
"total": 303,
"results": [
{
"spot_id": 112758,
"digital": true,
"media_name": "Digital Bulletins",
"construction": {
"construction_type": {
"name": "Freestanding"
}
},
"media_type": {
"name": "Bulletin"
},
"location": {
"dma_name": "New York, NY",
"state": "NY",
"geometry": {
"coordinates": [
-73.984625,
40.761033
],
"type": "Point"
}
},
"representations": [
[
[
{
"account": {
"name": "New York",
"parent_account_name": "Clear Channel"
},
"representation_type": {
"name": "Own"
}
}
]
]
]
}
]
}Example Response
Note: The layouts[].faces[].spots array is truncated in this example. A single face may contain many spots, especially for digital rotating displays.
{
"status": "success",
"total": 303,
"results": [
{
"audio": false,
"digital": true,
"full_motion": false,
"interactive": false,
"media_name": "Digital Bulletins",
"partial_motion": false,
"rotating": true,
"illumination_end_time": "23:59:59",
"illumination_start_time": "00:00:00",
"illumination_type": {
"name": "Backlit"
},
"classification_type": {
"name": "Roadside"
},
"construction": {
"construction_type": {
"id": "1",
"name": "Freestanding"
}
},
"media_type": {
"name": "Bulletin"
},
"placement_type": {
"name": "Set Back"
},
"status_type": {
"name": "Published - Measured"
},
"location": {
"county_id": "36061",
"county_name": "New York County",
"dma_id": "501",
"dma_name": "New York, NY",
"cbsa_code": "35620",
"cbsa_name": "New York-Newark-Jersey City, NY-NJ-PA Metro Area",
"state": "NY",
"zip_code": "10019",
"primary_artery": "Broadway",
"geometry": {
"coordinates": [
-73.984625,
40.761033
],
"type": "Point"
},
"geo_point": "dr5rukq41",
"places": [
{
"place_name": ""
}
],
"place_types": {
"name": "Central Business District"
},
"orientation": 180
},
"layouts": [
{
"id": 133527,
"audio": false,
"full_motion": false,
"interactive": false,
"partial_motion": false,
"rotating": true,
"spot_share_of_voice": "0.016666",
"faces": [
{
"id": 133527,
"width": 780,
"height": 540,
"spots": [
{
"id": 30988608,
"plant_spot_id": "000016-AU",
"rotating": true,
"audio": false,
"full_motion": false,
"partial_motion": false,
"interactive": false,
"max_frames": "1",
"spot_share_of_voice": "0.016666",
"spot_length": 60,
"measures": [
{
"viewcast": "20260308"
}
]
}
]
}
]
}
],
"representations": [
[
[
{
"account": {
"name": "New York",
"parent_account_name": "Clear Channel"
},
"representation_type": {
"name": "Own"
}
}
]
]
],
"spot_id": 133527,
"place": {
"place_id": "",
"place_name": ""
}
}
]
}Error Handling
The API returns appropriate HTTP status codes and error messages:
200 OK: Successful search with results400 Bad Request: Invalid filter parameters500 Internal Server Error: Server-side search error
Example error response when providing an array value for a filter:
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "[term] query does not support array of values"
}
],
"type": "x_content_parse_exception",
"reason": "[1:566] [bool] failed to parse field [filter]",
"caused_by": {
"type": "parsing_exception",
"reason": "[term] query does not support array of values"
}
},
"status": 400
}Rate limit exceeded response:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded your request quota. Please try again later.",
"details": "Maximum of 20 requests per minute allowed."
}
}Server error response:
{
"status": "error",
"message": {
"code": 14001,
"api-message": "error searching for spots",
"message": "unable to search spots"
}
}