Truely API · v1

UK postcode intelligence, programmatically.

Every figure on a Truely postcode page — council tax, deprivation, air quality, broadband, flood risk, schools, greenspace, twenty more — delivered as a single JSON response, keyed by UK postcode. Bearer-token authentication, edge-cached, sub-100 ms p50 from London. The same data layer that powers truely.uk, now addressable from your own code.

Overview #

The Truely API is a stateless, JSON-only HTTP service. Every endpoint lives under https://truely.uk/api/v1/. Authentication is by Bearer token. Errors conform to RFC 7807 (application/problem+json). All timestamps are ISO 8601 UTC. All responses carry an X-Request-ID for support correlation.

Under the hood the API runs on Vercel Edge in London, reads from the same Supabase cluster as the website, and is served from a multi-region CDN. Per-key 24-hour sliding-window rate limiting is enforced at the edge before any database read. All traffic is HTTPS-only.

i The Truely API is a data API, not a regulated advisory product. It returns figures and signals from the UK public record under the Open Government Licence v3.0. You are responsible for any decision derived from this data. See Licence & attribution.

Quick start #

Three steps from zero to your first response. Mint a key, send a request, parse JSON.

  1. Create a free account at truely.uk/signup and open the Developer tab. Click Mint key. The plaintext key is shown once — store it now (it never appears again).
  2. Send a GET request to /api/v1/postcode/{pc} with your key in the Authorization header.
  3. Parse the JSON. Done.
curl https://truely.uk/api/v1/postcode/SW18%201PB \
  -H "Authorization: Bearer tk_live_REPLACE_WITH_YOUR_KEY"

Successful response (truncated for brevity):

{
  "postcode": "SW18 1PB",
  "borough": "Wandsworth",
  "ward": "Thamesfield",
  "parliamentary_constituency": "Putney",
  "geo": { "lat": 51.45, "lng": -0.19 },
  "council_tax": {
    "band_d_gbp_per_year": 1028,
    "most_common_band": "C",
    "measurement_year": 2025,
    "source": "MHCLG / VOA"
  },
  "deprivation":  { "imd_decile": 7, "imd_release": "2025", "source": "MHCLG" },
  "air_quality":  { "pm25_ug_per_m3": 7.0, "no2_ug_per_m3": 20.6, "source": "DEFRA PCM" },
  "broadband":    { "pct_gigabit_capable": 100, "source": "Ofcom" },
  "flood_risk":   { "rivers_and_sea": "very_low", "surface_water": "low", "source": "Environment Agency" },
  "greenspace":   { "nearest_park_distance_m": 31, "source": "OS" },
  "meta": {
    "request_id": "3f0e2c8b-...",
    "fetched_at": "2026-05-19T12:34:56Z",
    "license":    "Open Government Licence v3.0",
    "docs":       "https://truely.uk/api"
  }
}

Authentication #

Every request must include a Bearer token in the Authorization header. Keys are 32 characters of base62 (plus the tk_live_ or tk_test_ prefix). They are case-sensitive.

Authorization: Bearer tk_live_AbCdEf0123456789ZyXwVuTsRqPoNm

Truely stores only a SHA-256 hash of your key — the plaintext exists in our systems for the duration of a single HTTP response, then is discarded. If you lose your key, you cannot recover it; rotate to a new one in your developer dashboard. Old keys can be revoked independently, so rotation is zero-downtime.

Keys prefixed tk_test_ behave identically but are scoped to a test tier with a relaxed rate limit and clearly-marked usage in your dashboard. Both prefixes hit the same production endpoint and the same data.

! Never expose a live key in client-side code. Call the API from your server. If you must call it from a browser, mint a key with a restricted CORS origin allow-list — empty by default means the key refuses browser calls entirely.

Rate limits #

Rate limiting is per-key, on a rolling 24-hour window. The window slides continuously — every successful request "ages out" 24 hours later. Three response headers report your standing on every 2xx response:

HeaderTypeDescription
X-RateLimit-LimitintegerDaily request ceiling for your key.
X-RateLimit-RemainingintegerRequests left in the current 24-hour window after this one.
X-RateLimit-ResetintegerUnix seconds when the window will be fully clear (worst case).

Exceeding the limit returns 429 Too Many Requests. The response body includes limit, used, tier and a link to upgrade. Use a token-bucket or fixed-pacing strategy client-side — exponential back-off on 429 with jitter is the conventional pattern.

Pricing & tiers #

Every Truely account ships with a free tier. Paid tiers upgrade your rate ceiling, unlock additional endpoints, and add an SLA-backed status page. Billing is via Stripe — see truely.uk/pricing for the monthly figures.

Free

£0/month
  • 25 requests/day
  • All v1 endpoints
  • Community support
  • Test keys included

Team

£199/month
  • 25,000 requests/day
  • 99.9% uptime SLA
  • Slack support channel
  • Custom CORS allow-list

Need higher volume, on-prem mirroring, or a custom data licence? Talk to us.

Endpoints #

The Phase A API ships with a single full-report endpoint. Subsequent phases add the borough, compare, and twins endpoints — they will appear here without breaking the v1 contract.

GET /api/v1/postcode/{pc}

Description

Returns the full Truely public-records report for a single UK postcode. The postcode is normalised server-side, so SW181PB, sw18 1pb and SW18%201PB all resolve to the same record.

Path parameters

FieldTypeDescription
pcstringUK postcode. Any common spacing or casing is accepted. URL-encode the space if you include one (SW18%201PB).

Response — 200 OK

FieldTypeDescription
postcodestringNormalised postcode, e.g. SW18 1PB.
boroughstringLocal authority district name (e.g. Wandsworth).
wardstringElectoral ward name.
parliamentary_constituencystringUK Parliament constituency.
geoobject{ lat, lng } in WGS84 decimal degrees.
council_taxobjectBand D rate (GBP/year), most-common band, measurement year, source attribution.
deprivationobjectIMD decile (1–10, 10 = least deprived), release year, source.
air_qualityobjectAnnual mean PM2.5 and NO₂ (µg/m³) from DEFRA's Pollution Climate Mapping.
broadbandobjectPercentage of premises gigabit-capable, source (Ofcom Connected Nations).
flood_riskobjectWorst-band rivers/sea and surface-water rating from the Environment Agency.
greenspaceobjectNearest publicly accessible park distance in metres.
metaobjectrequest_id, fetched_at (ISO 8601 UTC), licence, docs URL.

Possible errors

StatusTitleWhen
400Malformed postcodePath segment is not a recognisable UK postcode shape.
401Authentication required / Invalid API keyMissing, malformed, or unknown Bearer token.
404Postcode not foundPostcode is well-formed but not present in the ONS register (terminated or never issued).
429Rate limit exceededPer-key 24-hour quota reached.
500Upstream errorTransient failure reading from Supabase or postcodes.io. Retry with back-off.

Caching

Successful responses are CDN-cached for one hour with stale-while-revalidate. The authentication and rate-limit checks run before the CDN consults its cache, so your quota is always counted accurately.

Coming soon

The same authentication pattern applies to all endpoints below. They are queued in the order shown.

Errors #

Every non-2xx response is application/problem+json following RFC 7807. The shape is identical across endpoints, so you can write a single error handler once and reuse it everywhere.

{
  "type":       "https://truely.uk/api/errors/429",
  "title":      "Rate limit exceeded",
  "status":     429,
  "detail":     "You have used 25 of your 25 requests/day quota for the free tier...",
  "request_id": "3f0e2c8b-...",
  "limit":      25,
  "used":       25,
  "tier":       "free",
  "window":     "24h",
  "upgrade":    "https://truely.uk/pricing"
}

Status reference

StatusMeaningRetry?
400Bad RequestMalformed input — fix the request before retrying.No
401UnauthorisedMissing, malformed, or revoked API key.No
403ForbiddenNon-HTTPS request, or CORS origin not in the key's allow-list.No
404Not FoundPostcode (or other resource) exists in the URL shape but not in the data.No
429Too Many RequestsRate limit exceeded. Honour Retry-After if present.Yes, with back-off
500Server ErrorTransient upstream failure. Truely will see this in the logs.Yes, idempotent

Response headers #

HeaderOnDescription
X-Request-IDevery responseUnique per request. Include it in any support enquiry.
X-RateLimit-Limit2xx, 429Daily ceiling for the calling key.
X-RateLimit-Remaining2xx, 429Quota left after the current request.
X-RateLimit-Reset2xx, 429Unix seconds when the whole window will be clear.
Cache-Control2xxpublic, max-age=0, s-maxage=3600, stale-while-revalidate=7200 on cacheable endpoints; no-store on errors.
Content-Type2xxapplication/json; charset=utf-8.
Content-Typenon-2xxapplication/problem+json; charset=utf-8.

Versioning #

The API is versioned in the URL path: /api/v1/. Within v1, Truely will only add fields — never remove or rename one. New endpoints arrive as new paths. Removals or breaking renames will only ever happen in a v2, and v1 will run alongside v2 for at least 12 months after v2 is announced.

Treat every field as optional in your client. A missing field means we have no data for that postcode on that dataset (it does not mean the value is zero).

Data sources #

Every figure in a Truely response is sourced from an official UK government publisher, refreshed on each publisher's own cadence. The source field on every block names the publisher; the methodology page documents each source's update frequency and known limitations.

Licence & attribution #

All data returned by the Truely API is published by UK government bodies under the Open Government Licence v3.0. You may use the data in your own products, including commercially, subject to the OGL's attribution requirement. The attribution string we recommend is:

Contains UK public sector information licensed under the Open Government Licence v3.0.
Aggregated and delivered by Truely (https://truely.uk).

The Truely name, the truely wordmark, the editorial copy that surrounds the data, and the Truely Score composite are not OGL-licensed and remain Truely's property.

Status & uptime #

The free tier is best-effort. The Developer tier targets 99.5% monthly uptime. The Team tier carries a 99.9% SLA with service-credit remedies — see the Terms for the exact mechanism. Truely posts incident updates to status.truely.uk (incident page coming with the Team tier launch).

You can call GET /api/v1/health from your own monitoring to confirm the API is reachable and that all upstream datasets have refreshed in the last 48 hours.

Support #

Email hello@truely.uk for any of the following — include the X-Request-ID from a failing response if you have one:

Changelog #

Backwards-compatible additions land continuously. Breaking changes are only possible across major versions; none are planned for v1.

DateEndpointChange
2026-05-19/v1/postcode/{pc}v1 launch. Full postcode report, Bearer auth, RFC 7807 errors, 24-hour rolling rate limit.