Minting an Anytime tile grant

Create, read, and revoke Popcast Anytime tile-delivery grants. Grants are the capability that unlocks the TileJSON URL your map client consumes.

Tile access runs through grants: a minted record that authorizes your organization to fetch Popcast Anytime vector tiles. A grant returns a tile_json_url capability URL you drop into MapLibre or Mapbox GL JS.

All grant management endpoints are free (0 credits): grant CRUD and the TileJSON fetch are control-plane operations. Only the tile bytes (GET .../anytime/{layer}/{z}/{x}/{y}.mvt) are metered, at 1 credit per 1000 tiles.

Prerequisites

  • Your organization must be licensed for the popcast.anytime.segment_occ_tiles feature. This feature is manual-grant-only: an explicit grant row is required. Unlicensed orgs get 403 FEATURE_NOT_LICENSED. Contact sales for an explicit grant.
  • Credentials: a signed-in session token (Authorization: Bearer <token>) or an org-scoped X-API-Key. Anonymous callers cannot mint grants. Grants are attributed to the user who created them, so an API key must have been created by a user (see API_KEY_NO_AUDIT_USER below).

Create a grant

POST /v2/popcast/tiles/anytime/grants

Request body:

FieldTypeMeaning
namestring (max 120)Human-readable label, shown in the developer dashboard
tilesetsstring[]Tileset slugs (the catalog's slug field) from the discovery catalog. An empty array means every tileset currently published; the grant is stored with the expanded concrete list, so tilesets published later need a new grant. A slug that is not published is rejected with 403 TILE_LAYER_NOT_LICENSED.
allowed_originsstring[]Browser Origin allowlist for tilejson and tile fetches. Wildcards are not supported; list each origin literally. Use the explicit string "null" to allow requests that omit Origin (server-side rendering, curl).
expires_atISO 8601 datetimeGrant expiry. Note the tile-token inside the TileJSON independently expires 24h after each mint; re-fetch TileJSON before then.

Example:

curl -X POST "https://api2.mworks.com/v2/popcast/tiles/anytime/grants" \
  -H "X-API-Key: <your-org-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q3 campaign map",
    "tilesets": [],
    "allowed_origins": ["https://maps.example.com"],
    "expires_at": "2026-12-31T00:00:00Z"
  }'

Response (201):

{
  "data": {
    "grant_id": "01J5XH9K3W2Q5M0N8P7R4T6VYC",
    "tile_json_url": "https://api2.mworks.com/v2/popcast/tiles/anytime/grants/01J5XH9K3W2Q5M0N8P7R4T6VYC/tilejson",
    "tilesets": ["tiles_anytime_v2_3_21d529097c81af04_202501_202512_bg_v1", "tiles_anytime_v2_3_21d529097c81af04_202501_202512_zcta_v1", "..."],
    "allowed_origins": ["https://maps.example.com"],
    "expires_at": "2026-12-31T00:00:00Z",
    "created_at": "2026-08-08T20:05:11Z"
  }
}

The tile_json_url is a capability URL: treat it like an AWS S3 presigned URL. The opaque grant_id segment IS the credential; anyone holding the URL can render tiles from an allowed origin until the grant expires or is revoked. Two safety nets are built in: allowed_origins pins which sites can fetch tiles (Origin-enforced), and revoke kills the grant.

The entitlement is one-feature-all-tilesets: a license for Popcast Anytime Maptiles covers every published tileset. There is no per-segment scoping.

List, read, revoke

OperationEndpointNotes
List grantsGET /v2/popcast/tiles/anytime/grantsYour organization's grants, most recent first. Each grant carries usage_30d, reported as 0 today until usage reporting ships.
Read oneGET /v2/popcast/tiles/anytime/grants/{id}Scoped to the caller's org; expired or foreign grants read as 404.
RevokePOST /v2/popcast/tiles/anytime/grants/{id}/revokeRevokes the grant immediately. New TileJSON requests for it fail with 404, and tile requests that use tokens already minted from it are refused as well (401 UNAUTHORIZED with error.context.reason: grant_revoked), so revoking is the instant cutoff for a leaked URL. Revoking an already-revoked grant returns 200 with the unchanged record.

Error cases

  • 403 FEATURE_NOT_LICENSED: org has no explicit grant for popcast.anytime.segment_occ_tiles. Contact sales.
  • 403 TILE_LAYER_NOT_LICENSED: a tilesets[] entry names a slug Popcast Anytime does not publish. Fires on unpublished slugs only, never as a licensed-subset rejection (the entitlement is all-tilesets). The error's context.missing lists the offending slugs.
  • 403 API_KEY_NO_AUDIT_USER: the API key is not tied to a user, so the grant cannot be attributed. Mint with a signed-in session, or with an API key created by a user.
  • 403 TILE_GRANTS_REQUIRE_METERED: your organization has no pay-as-you-go (metered) billing. Contact sales to enable metered tile delivery.
  • 403 ORIGIN_NOT_ALLOWED: the fetch's Origin is not in allowed_origins.
  • 400: invalid request body. 401: missing or invalid credentials.

Deny envelope: every error response on this surface uses the standard envelope shape. Example for an unlicensed org:

{
  "error": {
    "code": "FEATURE_NOT_LICENSED",
    "message": "Your organization is not licensed for popcast.anytime.segment_occ_tiles.",
    "status": 403,
    "request_id": "req_e8281bd0f5a1",
    "product": "popcast",
    "context": {}
  }
}

Expired grants read as 404 NOT_FOUND (Grant expired.), not 403 or 410: a foreign, nonexistent, or expired grant id is indistinguishable from the outside. A revoked grant stays readable through the grant endpoints with revoked_at set, but its TileJSON returns 404 and every tile request made with a token minted from it is refused with 401 UNAUTHORIZED (grant_revoked), even if that token has not yet expired.

Token lifecycle

Each GET /tilejson mints a fresh tile token valid for 24 hours, embedded in tiles[]. A Popcast Anytime token never authorizes another product's tiles. The manifest's x-mw.refresh_after (82,800 seconds, 23h) tells clients when to re-fetch the TileJSON for a fresh token. Standard TileJSON consumers append the ?token= query to every tile request automatically; you do not call the .mvt endpoint by hand. Revoking the grant invalidates outstanding tokens immediately (see above).


Did this page help you?