# Mossforge DataBroker > Pay-per-call UK data and utility API gated by x402 micropayments on Base mainnet. No API keys, no accounts, no subscriptions — sign a payment, get an answer back. Built for autonomous AI agents and scripts to call directly. DataBroker serves UK vehicle data, fleet analytics, and a tier of identifier/geospatial/reference utility endpoints via the x402 protocol (https://x402.org). Every paid endpoint returns HTTP 402 with payment requirements until a valid signed USDC payment is attached, then settles on-chain and returns the data in the same response cycle. Base URL: https://api.databroker.mossforge.dev Network: Base mainnet (eip155:8453) Payment token: USDC Protocol: x402 (exact scheme) ## Start here - [Discover endpoint](https://api.databroker.mossforge.dev/v1/discover): machine-readable list of all enabled datasets, current prices, descriptions, and provenance (`kind`, `standard`, `deterministic`, `data_source`). No payment required. Agents should call this first to confirm current pricing before constructing a paid request. - [OpenAPI spec](https://databroker.mossforge.dev/openapi.yaml): full machine-readable schema for all routes, request/response shapes, and error codes. - [README](https://github.com/mossforge/databroker): human-readable documentation, integration examples in TypeScript and Python, and full sample responses. ## Dataset kinds Every entry in /v1/discover carries a `kind` field describing its provenance: - `cached` — a stored dataset backed by an ingestion pipeline (e.g. dvsa-mot). Full freshness semantics: ttl, staleness, /meta cache checks. - `computed` — a pure deterministic function (e.g. util-iban). The same key always returns the same answer, forever. Never cached, never stale. `deterministic: true` in discover and in every response. - `bundled` — a lookup against a static reference-data snapshot shipped with the service (e.g. util-airport), refreshed on the advertised cadence. `deterministic: false`, plus a `data_source` naming the upstream registry. Agents can use `kind` to decide caching strategy client-side: cache `computed` results indefinitely, cache `bundled` results up to ttl_seconds, treat `cached` per the envelope's staleness fields. ## Datasets ### DVSA MOT history - Endpoint: GET /v1/dvsa-mot/{registration} - Price: $0.005 USDC per call - Returns: full MOT test history for a UK vehicle by registration plate — vehicle details, pass/fail summary, mileage, and individual test records with defects. - Cache: 30 days. First-ever lookup for a registration triggers a live fetch (2-4 seconds); subsequent calls within 30 days return instantly. - Free metadata check: GET /v1/dvsa-mot/{registration}/meta — returns cache freshness without payment, useful for deciding whether to pay before issuing the paid request. ### DVSA MOT analytics - Endpoint: GET /v1/dvsa-mot-analytics/{key} - Price: $0.02 USDC per call - Returns: aggregated MOT statistics for a UK vehicle segment — pass rates, top failure defects, top advisories, mileage percentiles, clocking rates, fuel mix, and colour distribution, computed from the full DVSA bulk dataset. - Refresh: daily pipeline, data current to previous day. - Key format: family-specific, colon-delimited. See "Analytics key format" below. - Statistical reliability: rates and percentiles are withheld (returned as null) when the underlying sample size is below a minimum threshold, to avoid publishing misleading statistics from small samples. A `lowSample: true` flag and `minN` value are included when this happens. ### Utility endpoints (computed) - Endpoint pattern: GET /v1/{dataset_id}/{key} - Price: $0.001 USDC per call - Pure deterministic computations — validators, decoders, and algorithms exposed as single-purpose paid endpoints. Every response names the authoritative `standard` it implements and carries `deterministic: true`. - Malformed keys (wrong arity, garbage charset, absurd length) are rejected with HTTP 400 BEFORE payment — you never pay for an ill-posed question. But note: for validators, `valid: false` is a legitimate PAID answer. You pay for the verdict, not for verdict === true. - URL-encode keys containing `/`, spaces, or `+` (e.g. a tyre size `205/55R16 91V` becomes `205%2F55R16%2091V`). | dataset_id | Key format | Returns | |---|---|---| | util-vin | 17-char VIN | Structural validation, North American check digit, WMI region/manufacturer, VDS/VIS split, model year candidates (ISO 3779/3780, FMVSS 565) | | util-uk-plate | UK registration plate | Format era (current/prefix/suffix/dateless), area code, age identifier, registration period (DVLA formats) | | util-mot-due | YYYY-MM-DD (first registration date) | First MOT due date, whether now due, vehicle age, 40-year historic exemption flag (GB MOT rules) | | util-tyre-size | e.g. 205/55R16 91V (URL-encoded) | Section width, aspect ratio, rim diameter, overall diameter, load index → kg, speed rating → km/h (ETRTO) | | util-iban | IBAN string | Validity per SWIFT per-country lengths + MOD 97-10 check digits, country/BBAN parse (ISO 13616) | | util-isin | ISIN string | Validity, country prefix, NSIN, Luhn check digit (ISO 6166) | | util-cusip | CUSIP string | Validity, issuer/issue split, mod-10 check digit with *, @, # handling (ANSI X9.6) | | util-sedol | SEDOL string | Validity, weighted mod-10 check digit (LSE) | | util-lei | LEI string | Validity, 20-char structure, MOD 97-10 check digits (ISO 17442) | | util-card | Card number | Luhn validity and network detection by public prefix/length rules — not an issuer BIN lookup (ISO/IEC 7812) | | util-aba-rtn | 9-digit routing number | Validity, 3-7-1 weighted mod-10 check digit (ABA) | | util-gtin | GTIN-8/12/13/14, or compute: | Validity + type; compute mode returns the check digit and full code (GS1 mod-10) | | util-isbn | ISBN-10 or ISBN-13 | Validity plus bidirectional 10↔13 conversion (ISO 2108) | | util-issn | 8-char ISSN | Validity, weighted mod-11 check character (ISO 3297) | | util-container | Container number, e.g. MSKU3068821 | Validity, owner code, equipment category, serial, check digit (ISO 6346) | | util-imo | 7-digit IMO number | Validity, weighted check digit (IMO scheme) | | util-checkdigit | :: where algo ∈ luhn, verhoeff, damm, mod97-10, mod11-2 | verify → valid true/false; compute → check digit/character and full value | | util-geo | distance:lat1,lon1,lat2,lon2 or destination:lat,lon,bearingDeg,distanceKm | Great-circle distance (km/mi/nm) + initial bearing, or destination point (haversine, mean radius 6371.0088 km) | | util-geohash | encode:lat,lon[,precision] or decode: | Geohash string, or decoded centre point with bounding box | ### Utility endpoints (bundled reference lookups) - Endpoint pattern: GET /v1/{dataset_id}/{key} - Price: $0.002 USDC per call - Lookups against static reference-data snapshots shipped with the service, refreshed on the advertised cadence. `deterministic: false`; every response includes `data_generated_at` naming the snapshot date, and discover includes the upstream `data_source`. | dataset_id | Key format | Returns | Snapshot refresh | |---|---|---|---| | util-oui | MAC or OUI prefix, e.g. 00:00:5E or 00005E005300 | Vendor name/country from the IEEE OUI registry; flags locally-administered (randomised) and multicast addresses | ~30 days | | util-airport | LHR, EGLL, iata:LHR, icao:EGLL | Name, coordinates, elevation, country/region, municipality, scheduled service, IATA+ICAO codes (OurAirports) | ~30 days | | util-tz | zone:Europe/London[:2026-01-15] or country:GB | UTC offset at a moment, DST status, abbreviation, standard offset, countries; or zone list for a country (IANA tzdb + runtime ICU) | ~90 days | | util-currency | GBP or 826 | Name, numeric code, minor units, using entities, withdrawn-code history (ISO 4217) | ~90 days | | util-locode | GBLON or GB:LON | Place name, subdivision, decoded function classifiers (port/rail/road/airport…), status, coordinates (UNECE Rec 16) | ~180 days | ## Analytics key format The {key} segment is colon-delimited and varies by analytics family: - reliability: — e.g. reliability:ford Pass rates by age and mileage band, first-time pass rate, dangerous defect rate. - mileage:: — e.g. mileage:ford:5-8yr or mileage:ford:2019 Average annual mileage, percentile distribution, odometer clocking rate. Accepts either an age band or an exact registration year. - parc::: — e.g. parc:ford:diesel:5-8yr Vehicle population counts and recent testing activity for a make/fuel/age segment. - fuelmix: — e.g. fuelmix:2019 Fuel type distribution (petrol/diesel/electric/hybrid/other) for vehicles registered in a given year. - colour:: — e.g. colour:ford:2019 Top vehicle colours for a make/registration-year combination. - temporal — no parameters UK-wide MOT test volume, pass rate, and certificate expiry density by calendar month. Valid age bands: 0-3yr, 3-5yr, 5-8yr, 8-12yr, 12yr+ Valid fuel types: petrol, diesel, electric, hybrid, other Valid makes: ford, vauxhall, volkswagen, bmw, mercedes-benz, toyota, audi, nissan, peugeot, renault, honda, hyundai, kia, volvo, land rover, mini, seat, skoda, fiat, mazda, citroen, jeep, mitsubishi, suzuki, lexus, subaru, dacia, alfa romeo, jaguar, porsche, other ## Payment flow (x402) 1. Request without a payment header returns HTTP 402 with a PAYMENT-REQUIRED header describing the exact amount, recipient address, and network. 2. Sign an EIP-3009 transferWithAuthorization for the required USDC amount. 3. Retry the request with a PAYMENT-SIGNATURE header containing the signed payload. 4. DataBroker verifies and settles the payment on-chain, then returns the data with a PAYMENT-RESPONSE receipt header (also mirrored as X-PAYMENT-RESPONSE). Payment is atomic with data delivery — a 402 response means no funds have moved. You only pay on a 200 OK. x402 client libraries: - TypeScript/Node: @coinbase/x402-fetch - Python: x402 (PyPI) - Go: github.com/coinbase/x402-go ## Response shape Every successful paid response shares this envelope: ``` { "dataset": string, "key": string, "data": object, "fetched_at": string (ISO 8601), "fetch_status": "ok" | "error" | "partial", "source": string, "ttl_seconds": number, "stale": boolean, "deterministic": boolean (utility datasets only) } ``` Utility notes: - Computed utilities: `deterministic: true`, `stale` always false, `source` names the implemented standard, and `ttl_seconds` is pinned to a 10-year sentinel (~315360000) — the result never expires, so clients that cache on ttl_seconds can cache indefinitely. - Bundled utilities: `deterministic: false`, `source` names the upstream data source, `ttl_seconds` advertises the snapshot refresh cadence, and `data.data_generated_at` gives the snapshot date. ## Errors Errors return a structured body with a stable machine-readable `code` field. Agents should branch on `code`, never on `message` text, since message wording may change. ``` { "error": { "code": string, "message": string, "retryable": boolean, "retry_after_seconds": number (optional), "docs_url": string } } ``` Key codes: PAYMENT_INVALID (402, retryable — resign and retry), PAYMENT_SETTLEMENT_FAILED (402, retryable), UNKNOWN_DATASET (404, not retryable), ENTITY_NOT_FOUND (404, not retryable — final result, no MOT history exists), INGEST_IN_PROGRESS (503, retryable — wait retry_after_seconds and retry), BUCKET_NOT_SEEDED (404, retryable — pipeline may not have populated this segment yet). Utility datasets additionally reject malformed keys with a 400 before any payment is taken — the message states the expected key format; fix the key and retry, no funds have moved. ## Free routes (no payment) - GET /v1/health — uptime check - GET /v1/discover — list datasets, current prices, and provenance (kind/standard/deterministic/data_source) - GET /v1/{dataset}/{key}/meta — cache freshness for cached datasets, no data payload. For utility datasets this returns the kind, standard, and determinism info instead (there is no cache to inspect — computed results are never cached; bundled results advertise their snapshot cadence). ## Notes for agent developers - Always call /v1/discover before constructing a payment, since prices are configured server-side and may change without notice to this document. - Use the /meta endpoint to check staleness before paying if you want to avoid paying twice for the same lookup within the cache window (cached datasets only — computed utility results are deterministic and safe to cache client-side forever). - ENTITY_NOT_FOUND is a final, non-retryable result for dvsa-mot: it means DVSA has no MOT record for that registration (e.g. vehicle exempt, too new, or invalid plate), not a transient failure. - For utility validators, a `valid: false` result is a correct, complete, PAID answer — the endpoint sells the verdict, not confirmation. Do not treat `valid: false` as an error or retry it; the same key will deterministically return the same verdict. - Cheaper-than-implementing rule of thumb: at $0.001 per call, a utility endpoint is usually cheaper (in tokens and risk of subtle bugs) than generating and testing your own implementation of a checksum or standard. - This API has no authentication and no rate limiting beyond standard abuse protection — there is nothing to provision before making your first paid call beyond a funded Base wallet. Contact: support@mossforge.dev