Displays On Demand purchase flow and credits
Displays On Demand meters every operation in credits. This page explains the credit costs, idempotency guarantees, refund behavior, and the subscription window for direct-add profile access.
All endpoints are on the v2 base https://api2.mworks.com under the /v2/displays/* path. For the full endpoint reference, see Displays API reference.
Credit model
Every asset-library endpoint carries a base cost of 1 credit (displays_asset_crud). On top of the base cost, measurement purchases charge additional credits based on the measurement kind:
| Operation | Credit key | Credits | When charged |
|---|---|---|---|
| Any CRUD or measurement endpoint (base) | displays_asset_crud |
1 | Every call |
| Draft measurement purchase | viewcast_viewshed_purchase_draft |
150 | On POST /v2/viewcast/measurements/purchase/draft |
| Final measurement purchase | viewcast_viewshed_purchase_final |
300 | On POST /v2/viewcast/measurements/purchase/final |
| Direct measurement purchase | viewcast_viewshed_purchase_direct |
300 (total: 1 base + 299) | On POST /v2/viewcast/measurements/purchase/direct |
| Search | displays_search |
1 | On POST /v2/displays/search |
The purchase type (draft or final) rides in the path and the asset_id in the request body; there is no kind body field (sending one returns 400).
So a full lifecycle for one asset costs: 1 cr (create) + 151 cr (draft purchase: 1 base + 150 purchase) + 301 cr (final purchase: 1 base + 300 purchase) = 453 credits, plus any read/list/summary calls at 1 cr each.
Idempotency
The two purchase-style endpoints have different retry contracts:
POST /v2/displays/assets(create) takes no idempotency key and returns 200 synchronously. A retry creates a second asset. The only duplicate protection is the 409 duplicate-face guard, which fires when your organization already has an asset with the sameparty_display_idandspot_id(carried in therelated_parties[]entry withrole: 'owner'). Both fields are optional, so send them whenever you have them; without them a retried create silently produces a duplicate.POST /v2/viewcast/measurements/purchase/{type}(draft or final purchase) carries the idempotency key in the request body asmeasurement_request_id(a UUID), alongside theasset_id. TheIdempotency-Keyheader is rejected with 400. Replaying the samemeasurement_request_idwith the same body returns the original 202 result without queuing a second measurement or charging a second purchase. Replaying the same id with a different body returns 409idempotency_mismatch.
Informational-outcome auto-refund
Some measurement results are informational rather than measured. When a draft or final measurement completes with one of these outcomes, the purchase charge is automatically refunded:
no_coverage: the face's viewshed has no traffic coverage in the source data. No measured impressions are available.insufficient_data: the source data for the viewshed is too sparse to produce a reliable measurement.
In both cases the measurement result is delivered (status completed with the informational outcome in the result body), but the purchase credits (150 for draft, 300 for final) are returned to your account. The refund_credits field in the measurement result reflects the refunded amount. The base 1 cr endpoint cost is not refunded.
Failed-state refund
If a measurement enters the failed state (the measurement pipeline could not produce any result, informational or otherwise), the purchase charge is also automatically refunded. The refund_credits field in the failed result reflects the refunded amount. The base 1 cr endpoint cost is not refunded.
The 12-month subscription window and repurchase
When you purchase a display directly (POST /v2/viewcast/measurements/purchase/direct, 300 credits via viewcast_viewshed_purchase_direct; full contract on the Direct measurement purchase page), the API mints a locked final_measured asset owned by your organization. This starts a 12-month subscription window for that display.
- For the 12 months the window is open,
GET /v2/viewcast/profiles/{display_id}for that display costs only the base 1 cr (owned read). - The window is a fixed 12 months and does not auto-renew (ADR-0037). At expiry the profile read fails closed for that display. To keep access, your organization re-purchases the same
display_idthrough the same direct purchase path, which opens a new 12-month window. Because a direct-purchased asset is locked atfinal_measured(PATCH refine and DELETE archive both return 409), repurchase after lapse is the renewal path.
Reading profiles: the licensed-read contract
GET /v2/viewcast/profiles/{display_id} is a pure licensed read:
- Unowned caller: 403
FEATURE_NOT_LICENSED, whether or not thedisplay_idexists (the answer reveals nothing about display existence). The error body points to the purchase surface:POST /v2/viewcast/measurements/purchase/direct(see Direct measurement purchase). No charge. - Owned caller (your org owns a measurement for the display, subscription unexpired): 200 with the full display profile at the base 1 cr.