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.

FieldTypeConstraintsDescription
latnumber-90 to 90WGS-84 latitude of the display face anchor.
lonnumber-180 to 180WGS-84 longitude of the display face anchor.
face_height_innumbergreater than 0Face height in inches.
face_width_innumbergreater than 0Face width in inches.
orientationnumber0 to 360Face orientation in degrees. 0 = north, 180 = south.
orientation_lock_typestringenum: no_move, limited_move, full_rangeHow 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_rulestringenum: veh_metres, nearest, busiestRule 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.

OutcomeHTTP StatusMeaning
validated200The face configuration produced a valid viewshed with measurable road segments.
no_coverage200The location is outside the geographic coverage area.
insufficient_data200The location is in coverage, but the underlying data is not sufficient to build a viewshed.
rejected200The 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 validated outcome 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 StatusCodeMeaning
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

HeaderDescription
X-Request-IdUnique request identifier.
X-MW-Credits-UsedNumber of credits charged (5).
X-MW-WorkerWorker that handled the request (viewcast).
X-MW-Cache-StatusCache hit or miss (HIT or MISS).
Cache-ControlStandard 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).


Did this page help you?