Viewcast Search

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_size cannot 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 accepts filters)
    • 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. Requires lat (number), lon (number), and distance (string with unit, e.g., "1km", "5mi")
  • geo_bounding_box: Object - Filter by geographic bounding box. Requires top_left and bottom_right objects, each with lat and lon

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) displays
  • full_motion: Boolean - Filter by full motion video capability
  • interactive: Boolean - Filter by interactive capability
  • rotating: Boolean - Filter by rotating display
  • audio: 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 as spot_id after field renaming). When fieldSet is not provided, all default fields are returned. The status and total response fields are always included regardless of fieldSet.

Example field paths:

  • "id" - Spot ID (returned as spot_id in 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 results
  • 400 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 query
  • total: Number - Total count of matching inventory records
  • results: Array of inventory objects (see Response Fields below)

Response Fields

Each inventory result contains:

Top-Level Fields:

  • spot_id: Integer - Geopath Spot ID (renamed from id in the underlying index)
  • digital: Boolean - Whether the display is digital
  • audio: Boolean - Audio capability
  • full_motion: Boolean - Full motion video support
  • partial_motion: Boolean - Partial motion support
  • interactive: Boolean - Interactive capability
  • rotating: Boolean - Whether spots rotate on the face
  • media_name: String - Operator's media name (e.g., "Digital Bulletins", "Transit Shelters (TSA)")

Illumination:

  • illumination_type: Object with name (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 with name ("Roadside" or "Place Based")
  • construction: Object containing construction_type with id and name
  • media_type: Object with name (e.g., "Bulletin", "Poster", "Panel")
  • placement_type: Object with name (e.g., "Set Back", "Curbside", "Dining Area")
  • status_type: Object with name (e.g., "Published - Measured")

Location:

  • location: Object containing:
    • state: String - State abbreviation
    • county_id: String - County FIPS code
    • county_name: String - County name
    • dma_id: String - DMA identifier
    • dma_name: String - DMA name
    • cbsa_code: String - CBSA code
    • cbsa_name: String - CBSA name
    • zip_code: String - ZIP code
    • primary_artery: String - Primary road or intersection description
    • geometry: GeoJSON Point with coordinates [longitude, latitude] and type
    • orientation: Number - Face orientation in degrees
    • place_types: Object with name (e.g., "Central Business District", "Suburban")

Layouts (Face & Spot Detail):

  • layouts: Array of layout objects, each containing:
    • id: Integer - Layout/frame ID
    • faces: Array of face objects with:
      • id: Integer - Face ID
      • width: Integer - Face width (inches)
      • height: Integer - Face height (inches)
      • spots: Array of spot objects with:
        • id: Integer - Spot ID
        • plant_spot_id: String - Operator's internal spot identifier
        • spot_share_of_voice: String - Share of voice as decimal
        • spot_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 name
    • account.parent_account_name: String - Parent operator name (e.g., "Clear Channel", "JCDecaux")
    • representation_type.name: String - Representation type (e.g., "Own")

Place:

  • place: Object with place_id and place_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 results
  • 400 Bad Request: Invalid filter parameters
  • 500 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"
    }
}