Partner Device Monetization Requirements

Every partner device registration and lookup response (POST /v1/partner/device, POST /v1/partner/devices/batch, GET /v1/partner/device/:id, GET /v1/partner/devices) carries a monetization_status and a structured requirements object — modeled directly on Stripe's account.requirements.currently_due. Instead of silently accepting a registration that can never actually serve ads, the response tells you exactly what's missing and how to fix it.


{
  "monetization_status": "blocked",
  "requirements": {
    "currently_due": [
      {
        "code": "location_awaiting_device_gps",
        "field": "location",
        "reason": "awaiting_device_gps",
        "message": "This mobile screen has no location yet. Send a GPS fix in the heartbeat (location.lat/lng) and it resolves automatically.",
        "doc_url": "https://api.trillboards.com/docs/monetization-requirements#location_awaiting_device_gps"
      }
    ],
    "eventually_due": []
  }
}

monetization_status values

currently_due entries block (or limit) monetization right now. eventually_due entries don't block serving — they improve creative selection / targeting quality and are worth fixing, but there's no rush.

A device is never refused registration for missing location: it is created, and the response says which rails can serve it until a position arrives.

Location capability

Every response also carries location_capability: where the screen's location comes from, and, per rail, whether that rail has the location it needs.


{
  "location_capability": {
    "position": "fleet_market",
    "rails": {
      "inventory_feed": { "status": "ready", "location_source": "fleet_market", "reason": null },
      "geo_targeted_demand": { "status": "blocked", "location_source": null, "reason": "awaiting_device_gps" },
      "visit_attribution": { "status": "blocked", "location_source": null, "reason": "awaiting_device_gps" }
    }
  }
}

position — precise (the screen or its device has coordinates), fleet_market (no coordinates of its own; your account's declared fleet market location lists it), or none.

RailWhat it readsReady from
inventory_feedThe programmatic player feed, which accepts a fleet market locationThe screen's or device's own coordinates (screen, device), or your fleet's declared market location (fleet_market) when it is complete and its state can be expressed as an ISO 3166-2 code
geo_targeted_demandGeo-targeted programmatic demand, and the marketplace placement registries that publish a screen's own coordinateThe screen's or device's own coordinates (screen, device)
visit_attributionVisit-attribution location dataThe screen's own coordinates and a supported country (screen)

monetization_status is computed over inventory_feed and geo_targeted_demand; visit_attribution is a measurement capability and does not change it.

A blocked rail's reason:


location_awaiting_device_gps

How to fix: this is self-healing — no separate API call needed. Include a location object with a real GPS fix in the device's heartbeat body:


{
  "location": {
    "lat": 45.5017,
    "lng": -73.5673,
    "accuracy_m": 12,
    "heading": 180,
    "speed_mps": 8.3,
    "source": "gps",
    "timestamp": 1784800000
  }
}

lat/lng (or latitude/longitude) are the only required fields; the rest are optional. The very next heartbeat that includes a valid fix resolves this requirement automatically. Note this is heartbeat-only — location is not read from the device registration/PATCH body's location.lat/lng fields for this particular gate on mobile screens, since a one-time registration-time coordinate goes stale as a moving screen travels.

location_unresolvable

How to fix: on POST/PATCH /v1/partner/device, send location.lat / location.lng directly, or a full street address, or at minimum location.city + location.state.

enrichment_failed

How to fix: verify the location and venue details are accurate and re-save the device. If it fails again, contact support with the device's external_device_id and screen_id.

display_size_missing

How to fix: send display.width and display.height in pixels on POST /v1/partner/device (registration) or PATCH /v1/partner/device/:id (update anytime after registration). This is not an automatic/heartbeat field — the SDK must report it explicitly.