Authentication
Send X-RapidAPI-Key and X-RapidAPI-Host on RapidAPI. GET /v1/planning/health is public and returns {"status":"ok","version":"1.0.0","service":"planning-api"}.
Search
GET /v1/planning/applications
Returns applications, newest first by received date. At least one of uprn, postcode, outcode or council is required. Filters combine.
| Parameter | Type | Values |
|---|---|---|
uprn | string | 1 to 12 digits, for example 2465214361. |
postcode | string | Full UK postcode, for example LE1 5DE. Spaces and case are ignored. If sent with outcode, postcode is used. |
outcode | string | For example LE1. |
council | string | A council name as listed by /v1/planning/councils. Case is ignored. |
decision_status | string | One value from Values. |
type | string | One value from Values. |
size | string | small, medium or large. |
received_from | date | YYYY-MM-DD. Received on or after this day. |
received_to | date | YYYY-MM-DD. Received on or before this day. |
updated_since | date | YYYY-MM-DD. Record changed on or after this day. |
limit | integer | 1 to 50. Default 25. |
cursor | string | page.next_cursor from the previous page. |
Searches by outcode or council cover the last 12 months unless you set received_from. The response says so in query.received_from_defaulted. Searches by uprn or postcode cover all years.
GET /v1/planning/applications?postcode=LE1%205DE GET /v1/planning/applications?outcode=LE1&decision_status=permitted&type=full GET /v1/planning/applications?council=Leicester&received_from=2026-01-01&limit=50
{
"data": [ { "application_id": "ExampleCouncil/26/00123/HOU", "council": "ExampleCouncil", ... } ],
"page": { "limit": 25, "next_cursor": "MjAyNi0wNy0xNXw0Mg" },
"query": { "received_from": null, "received_from_defaulted": false, "received_to": null },
"disclaimer": "Planning data is provided \"as is\" ..."
}
next_cursor is null on the last page. Every response includes disclaimer.
Planning history for a UPRN
GET /v1/planning/uprn/{uprn}/applications
Every application we hold for that UPRN, newest first, all years. Accepts decision_status, type, limit and cursor. An unknown UPRN returns an empty list, not an error.
One application
GET /v1/planning/applications/{application_id}
Use the application_id exactly as returned by a search. It contains slashes; leave them as they are. Returns 404 if there is no such application.
Councils
GET /v1/planning/councils
Every council in the data, with latest_received (the most recent received date we hold), days_since_latest_received, freshness, latest_update (when we last changed one of its records) and applications_last_90_days. freshness is current (a new application within 2 weeks), delayed (2 to 6 weeks) or stalled (longer). A stalled council has stopped publishing to our source, so treat its newest applications as missing. The list covers councils with applications in the last two years. as_of says when it was last built, which happens every few hours. If you call it in the minute after a restart it may answer 503 while the first build finishes; try again.
The record
Every field is always present. A field is null when we have no value for it.
| Field | Type | Meaning |
|---|---|---|
application_id | string | Stable identifier for the application. Use it with /applications/{application_id}. |
council | string | Council name, as in /councils. |
council_reference | string | The council's own reference. |
alt_reference | string | Another reference used by the council, if any. |
related_to | string | Reference of a related application, if recorded. |
uprn | string | Property UPRN, when matched. See About UPRNs. |
site_address | string | Site address as given on the application. |
site_postcode | string | Postcode of the site, when recorded. |
latitude, longitude | number | WGS84 coordinates of the site. Both are null if either is missing or outside Great Britain. |
proposal | string | The proposal, as written by the council. Free text. |
type | string | Application class. See Values. |
council_type | string | The council's own application type wording. |
size | string | small, medium or large. |
decision_status | string | Outcome class. See Values. |
council_status | string | The council's own status wording. |
council_decision | string | The council's own decision wording, such as Pending. |
decision_route | string | The route to the decision, such as Delegated or Committee. A body, not a person. |
received | date | The date the council recorded as the start of the application. |
validated | date | Date the application was validated, where recorded. |
consultation_start, consultation_end | date | Consultation period, where recorded. |
target_date | date | Date by which the council aims to decide. |
decided_on | date | Date of the decision, once decided. |
permission_expires | date | When a permission lapses, where recorded. |
updated_at | timestamp | When this record last changed in our data. |
ward, parish | string | Where recorded. |
documents_count, comments_count, constraints_count, statutory_days, dwellings_proposed | integer | Counts as published by the council: documents, public comments, constraints, statutory days for the decision, and dwellings proposed. |
links.council_page | string | The application on the council's website. |
links.documents, links.comment, links.map | string | The council's documents, comment form and map for the application, where available. |
Dates are YYYY-MM-DD. Fields are filled in as the council publishes them, so recent applications have fewer than older ones.
{
"application_id": "ExampleCouncil/26/00123/HOU",
"council": "ExampleCouncil",
"council_reference": "26/00123/HOU",
"alt_reference": null,
"related_to": null,
"uprn": "100000000001",
"site_address": "1 Example Road, Exampletown",
"site_postcode": "AB1 2CD",
"latitude": 52.1,
"longitude": -2.2,
"proposal": "Single storey rear extension",
"type": "full",
"council_type": "Householder Planning",
"size": "small",
"decision_status": "undecided",
"council_status": "Pending Decision (Consultation)",
"council_decision": "Pending",
"decision_route": "Delegated",
"received": "2026-07-15",
"validated": "2026-07-16",
"consultation_start": null,
"consultation_end": "2026-08-05",
"target_date": null,
"decided_on": null,
"permission_expires": null,
"updated_at": "2026-07-16T12:24:23",
"ward": null,
"parish": null,
"documents_count": null,
"comments_count": null,
"constraints_count": null,
"statutory_days": null,
"dwellings_proposed": null,
"links": {
"council_page": "https://planning.example.gov.uk/application/26-00123-HOU",
"documents": null,
"comment": null,
"map": null
}
}
The example is illustrative.
Values
decision_status
undecided | Still being considered. |
permitted | Permission or consent granted. |
conditions | Granted subject to conditions, or a conditions-related decision. |
rejected | Refused. |
withdrawn | Withdrawn by the applicant or the council. |
unresolved | Closed or lapsed without a recorded outcome. |
referred | Referred to another body for decision. |
For the exact wording the council used, read council_status and council_decision.
type
full, outline, amendment, conditions, trees, heritage, advertising, telecoms, other. Use council_type for the council's own category.
About UPRNs
The UPRN is matched to the address on the application. It is a match to the address, not a guarantee about the proposal.
uprnisnullwhen we have no match. This is common for land and site-level applications, multi-plot schemes, new addresses that are not yet in address registers, and addresses too vague to match.- For a block of flats the UPRN may identify one unit or the building, depending on how the council wrote the address.
- To find applications with no UPRN, search by
postcode. - UPRNs are matched automatically and can be wrong. Check any match that matters.
Coverage and freshness
The data covers councils in England, Scotland and Wales, with applications going back to 2000. Councils publish at different speeds, and a few are updated less often than the rest, or are not covered. Use /v1/planning/councils to see each council's latest application and recent volume, and judge freshness for the places you rely on. New applications usually appear a few days after the council receives them, because councils publish on their own schedule, so the most recent days are always incomplete. Changes to existing applications, such as decisions, are picked up every day or two. A recent application may not appear yet, and recent records change as councils update them.
London
From 2019, applications for most London planning authorities come from the Planning London Datahub, which the Greater London Authority runs and the boroughs' own planning systems feed. These records have the same fields as the rest and nearly always carry a UPRN. A few fields are always null for them: alt_reference, related_to, parish, consultation_start, the counts, and the documents, comment and map links. validated is the same as received. Their application_id looks like Harrow-PL_1881_26, with no slash. Bromley, Brent, Ealing and Kensington and Chelsea are not yet current in the Datahub, so they come from our main source, as do all London applications received before 2019.
Contains public sector information licensed under the Open Government Licence v3.0. London applications from 2019: Planning London Datahub, Greater London Authority. While London data is included, every response carries this in attribution.
What is not included
Applicant and agent names and addresses, agent contact details and the case officer's name are not returned. The council's own pages, which links point to, may show them; that content is outside this API.
Errors
Errors return JSON: {"error": "bad_request", "message": "..."}.
| Status | Meaning |
|---|---|
400 | The request is not valid: no uprn, postcode, outcode or council; a value that does not parse; an unknown decision_status, type, size or council; or a bad cursor. The message says which. |
401 | Missing or invalid credentials. |
404 | No application with that application_id. |
422 | A parameter failed validation, such as limit=100 or a date that is not YYYY-MM-DD. |
503 | The service is temporarily unavailable. |