Display Validation
Synchronously validate a display face: submit anchor, dimensions, orientation, lock type, and primary-road rule to get the outcome, resolved orientation, road and segment analysis, viewshed geometry, and in-frame display detection.
Display Validation
The Viewcast Display Validation endpoint provides synchronous validation of a
display face. You submit an anchor location, physical dimensions, an
orientation, an orientation lock type, and a primary-road rule, and the
endpoint returns the validation outcome, the resolved orientation, the road
and segment analysis, the viewshed and search geography as GeoJSON polygons,
and a list of other display faces detected within the frame.
This is a delivery-mechanism addition over the same viewshed derivation used by
the Displays On Demand surface. It lets you check whether a
given face configuration will produce a valid, measurable viewshed before
committing to a purchase or asset record.
The auto-built endpoint-by-endpoint API reference (Redoc, rendered from the
OpenAPI spec) is available at /docs/api/viewcast/.
Authentication and Access
The endpoint is authenticated with an X-API-Key header using an
org-scoped API key. Any caller who has created an API key, including
anonymous signups, and holds enough credits can call this endpoint. The
endpoint is intentionally not gated by a license or feature key.
Request
The request body is a strict JSON object (additionalProperties: false) with
seven required fields. No optional fields are accepted.
| Field | Type | Constraints | Description |
|---|---|---|---|
lat | number | -90 to 90 | WGS-84 latitude of the display face anchor. |
lon | number | -180 to 180 | WGS-84 longitude of the display face anchor. |
face_height_in | number | greater than 0 | Face height in inches. |
face_width_in | number | greater than 0 | Face width in inches. |
orientation | number | 0 to 360 | Face orientation in degrees. 0 = north, 180 = south. |
orientation_lock_type | string | enum: no_move, limited_move, full_range | How the orientation may be adjusted by the system. no_move keeps the submitted orientation; limited_move and full_range allow the system to rotate the face to find a valid viewshed. |
primary_road_rule | string | enum: veh_metres, nearest, busiest | Rule for selecting the primary road segment. veh_metres prioritizes vehicle-metre exposure; nearest selects the closest road; busiest selects the highest-AADT road. |
Example Request
A Phoenix roadside billboard at 33.4484, -112.074, 14 in tall by 48 in wide,
oriented south (180 degrees), locked to the submitted orientation, with the
vehicle-metres primary-road rule:
curl -X POST https://api2.mworks.com/v2/viewcast/display-validation \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"lat": 33.4484,
"lon": -112.074,
"face_height_in": 14,
"face_width_in": 48,
"orientation": 180,
"orientation_lock_type": "no_move",
"primary_road_rule": "veh_metres"
}'Response
A successful call returns HTTP 200 with a {data, meta} envelope. The data
object carries the validation result; the meta object carries request and
billing metadata.
Response Envelope
{
"data": {
"outcome": "validated",
"requested_latitude": 33.4484,
"requested_longitude": -112.074,
"face_height_in": 14,
"face_width_in": 48,
"orientation": 180,
"orientation_lock_type": "no_move",
"chosen_orientation": 180,
"primary_road_rule": "veh_metres",
"primary_road_bearing": 180,
"served_direction": "northbound",
"primary_segment_id": "1234567890",
"primary_highway": "I-17",
"primary_aadt": 250000,
"primary_osm_way": 123456789,
"primary_way_aadt": 125000,
"primary_way_frontage_m": 45.2,
"primary_way_segments": 3,
"segments": [
{
"segment_id": "1234567890",
"highway": "I-17",
"aadt": 250000,
"osm_way": 123456789,
"way_aadt": 125000,
"way_frontage_m": 45.2,
"way_segments": 3,
"direction": "northbound",
"bearing": 180
}
],
"radius_m": 500,
"search_geography": { "type": "Polygon", "coordinates": [[[...]]] },
"viewshed": { "type": "Polygon", "coordinates": [[[...]]] },
"urbanicity": "urban",
"urbanicity_year": 2024,
"traffic_year": 2024,
"osm_vintage": "2024-06",
"in_frame": [
{
"geometry": { "type": "Point", "coordinates": [-112.074, 33.449] },
"sightline": "direct",
"occlusion": false,
"display_id": "abc-123",
"distance_m": 120.5
}
]
},
"meta": {
"request_id": "req_abc123",
"credits_used": 5,
"product": "viewcast",
"cached": false,
"provenance": {
"source": "mworks-product.viewcast.sketch_viewshed_v0",
"source_doc": "https://www.mworks.com/docs/viewcast/viewcast-display-validation/",
"methodology_version": "sketch_viewshed_v0",
"data_vintage": "2024-06-01",
"data_freshness": "annually",
"data_latency_days": 0,
"data_maturity": "production"
}
}
}Data fields beyond those listed above are passed through unmodified from the
underlying BigQuery procedure. The segments[] array contains per-segment
road analysis; the in_frame[] array contains other display faces detected
within the viewshed frame. The search_geography and viewshed fields are
GeoJSON polygons.
Outcome Taxonomy
The outcome field in data reports one of four values. A rejected outcome
is a successful HTTP 200 response, not an HTTP error. The reason is carried in
the error_message field when present.
| Outcome | HTTP Status | Meaning |
|---|---|---|
validated | 200 | The face configuration produced a valid viewshed with measurable road segments. |
no_coverage | 200 | The location is outside the geographic coverage area. |
insufficient_data | 200 | The location is in coverage, but the underlying data is not sufficient to build a viewshed. |
rejected | 200 | The submitted parameters were rejected (e.g. the orientation lock type prevents the system from rotating the face to reach a drivable road). error_message carries the reason. |
PROVISIONAL: as of 2026-09-02, only the
validatedoutcome branch has
been live-verified end to end. The four outcomes above are the intended
value set and are documented here as the contract.
Cost and Caching
Each call costs 5 credits total (1 router base credit plus 4 handler delta
credits), billed via the viewcast_display_validation operation. This is
equivalent to $0.25 per call at the standard credit rate.
Results are cached for 24 hours in KV, keyed by the anchor coordinates rounded
to 6 decimal places plus all input parameters. Cache hits are still charged 5
credits. The cached boolean in meta indicates whether the response was
served from cache. The X-MW-Cache-Status response header reports HIT or
MISS.
Errors
All errors use the standard error envelope:
{"error": {"code", "message", "status", "request_id", "docs_url"}}
| HTTP Status | Code | Meaning |
|---|---|---|
| 400 | (varies) | Invalid request body or schema validation failure. |
| 401 | (varies) | Missing, invalid, or non-org-scoped API key. |
| 402 | (varies) | Insufficient credits to complete the call. |
| 503 | (varies) | The upstream validation service is unavailable. |
Response Headers
| Header | Description |
|---|---|
X-Request-Id | Unique request identifier. |
X-MW-Credits-Used | Number of credits charged (5). |
X-MW-Worker | Worker that handled the request (viewcast). |
X-MW-Cache-Status | Cache hit or miss (HIT or MISS). |
Cache-Control | Standard HTTP cache control header. |
Methodology
The Display Validation endpoint uses the same viewshed derivation as the
Displays On Demand surface (/v2/displays/*). The viewshed geometry, road
segment matching, and in-frame display detection follow the same model
described in the Viewcast Methodology.
No methods-documentation delta was judged necessary for this endpoint. The
validation is a synchronous delivery-mechanism addition over the existing
viewshed derivation, not a new methodology. This was a deliberate decision
made under MA-123 (2026-09-03).
Updated about 2 hours ago
