Planning data (beta)

Planning Applications API

Find planning applications by postcode, near a point, or matched to an address. Each result has the proposal, status, decision and a link to the council record.

Endpoint

GET/api/v1/planning/applications

Provide postcode, address and postcode, or lat and lng. Every response includes beta: true and an attribution object.

Beta: read this before you rely on it

  • We collect applications for some councils only. If we do not collect a council, the response says coverage.status: "not_covered" and you are not charged. An empty list from a council we do not collect tells you nothing about that address.
  • For councils we do collect, older applications may be missing. Check coverage.earliestReceivedDate for the oldest date we hold and coverage.lastCollectedAt for when we last checked the council.
  • Applications are not linked to UPRNs. An address search compares the house number or name and street with the address the council published, so a match can be wrong, and a misspelt or unusual council address can be missed.
  • A search centred on a point checks the council for that point. Applications just over a council boundary may not appear.
  • Document links go to the council website. We do not copy or host documents, and councils sometimes move or remove them.
  • Source material belongs to the publishing council. Each result includes sourceUrl for the council record.

Pricing

RequestCredits
Search by postcode or by lat and lng3
Search by address and postcode (with match values)5
Any search where we do not collect the council0
One application with documents and timeline2
Application id not found0
Coverage check0
Property Profile section: ?with=planningApplications+5
Property Due Diligence option: planningApplications=true+3

Address matching

Send address with postcode and each application gets a match value:

property
The street and the house number or name match the application address. A range such as 12-16 matches numbers on the same side inside it.
same_street
The street matches but the number or name does not.
nearby
Within the search radius but on another street, or the address could not be read.

Other endpoints

GET/api/v1/planning/applications/{id}

One application by the id from a search. Returns the timeline, the decision notice link when the council published one, and links to each document on the council website.

{
  "success": true,
  "beta": true,
  "data": {
    "id": "exampleton:24-00123-FUL",
    "reference": "24/00123/FUL",
    "status": "Granted",
    "outcome": "approved",
    "decision": "Grant permission subject to conditions",
    "sourceUrl": "https://planning.exampleton.gov.example/applications/24-00123-FUL",
    "timeline": [
      {
        "kind": "decision",
        "title": "Decision issued",
        "date": "2024-05-02",
        "precision": "day",
        "sourceUrl": "https://planning.exampleton.gov.example/applications/24-00123-FUL"
      }
    ],
    "decisionNotice": {
      "title": "Decision notice",
      "url": "https://planning.exampleton.gov.example/documents/123"
    },
    "documents": [
      {
        "id": "123",
        "title": "Decision notice",
        "category": "Decision",
        "publishedDate": "2024-05-02",
        "url": "https://planning.exampleton.gov.example/documents/123"
      }
    ]
  },
  "attribution": {
    "source": "Local planning authority public registers, collected by Property Insights",
    "notice": "Source material belongs to the publishing council. Follow each sourceUrl to the council record. Documents are linked, not copied."
  }
}
GET/api/v1/planning/coverage?postcode=ZZ1%201ZZ

Free. Tells you whether we collect the council for a postcode, the earliest received date we hold and when we last collected it.

{
  "success": true,
  "beta": true,
  "data": {
    "input": {
      "postcode": "ZZ1 1ZZ"
    },
    "coverage": {
      "status": "covered",
      "ladCode": "E00000001",
      "authority": "Exampleton District Council",
      "earliestReceivedDate": "2015-01-01",
      "lastCollectedAt": "2026-10-26T06:00:00.000Z",
      "message": "Applications received before earliestReceivedDate, or published after lastCollectedAt, may be missing."
    }
  },
  "attribution": {
    "source": "Local planning authority public registers, collected by Property Insights",
    "notice": "Source material belongs to the publishing council. Follow each sourceUrl to the council record. Documents are linked, not copied."
  }
}

Billing details in the response

Successful chargeable JSON responses include a top-level billing object. The endpoint examples on this page focus on the endpoint-specific data, so this repeated block may not be shown in every example.

"billing": {
  "mode": "prepaid",
  "creditsCharged": 1,
  "creditsRemaining": 1999,
  "creditsRefreshAt": "2026-08-14T09:30:00.000Z"
}
Field or headerMeaning
billing.creditsCharged
X-Credits-Charged
Credits charged by this call. Failed and non-chargeable calls return 0 in the header.
billing.creditsRemaining
X-Credits-Remaining
The credit balance after the call.
billing.creditsRefreshAt
X-Credits-Refresh-At
The next monthly credit refresh as an ISO 8601 timestamp. Trial and non-renewing balances return null and omit the header.

All authenticated API-key calls expose the billing headers, including validation errors and zero-credit status or management requests. Only successful chargeable JSON responses add the billing object to the response body.

When credits run out

If your balance is lower than the cost of a request, the API returns HTTP 402 and charges nothing. The error includes the credits needed, your balance and a link to change plan.

{
  "statusCode": 402,
  "statusMessage": "Payment Required",
  "data": {
    "success": false,
    "error": {
      "code": "INSUFFICIENT_CREDITS",
      "message": "This request costs 35 API credits. Upgrade your plan or wait for your monthly refresh: https://propertyinsights.co.uk/billing",
      "required": 35,
      "available": 12,
      "upgradeUrl": "https://propertyinsights.co.uk/billing"
    }
  }
}

Parameters

NameRequiredTypeDescription
postcodeNostringFull UK postcode. On its own, returns applications recorded at that postcode.
addressNostringHouse number or name and street. Requires postcode. Searches around the postcode and adds a match value to each result.
latNonumberLatitude when postcode is omitted.
lngNonumberLongitude when postcode is omitted.
radiusNointegerSearch radius in metres for coordinate and address searches, up to 1,000. Defaults to 250.
receivedFromNostringOnly applications received on or after this date (YYYY-MM-DD).
receivedToNostringOnly applications received on or before this date (YYYY-MM-DD).
outcomeNostringapproved, refused, withdrawn, other or unknown.
limitNointegerApplications per page, up to 100. Defaults to 25.
cursorNostringnextCursor from the previous response, to fetch the next page.

Source and coverage

Source
Local planning authority public registers, collected by Property Insights. Source material belongs to the publishing council.
Coverage
Some councils in England, Wales, Scotland and Northern Ireland. Use /api/v1/planning/coverage to check a postcode.

An empty result only means no applications were found in the records we hold. Check coverage.status and coverage.earliestReceivedDate before treating it as a clean history.

Example request

curl -X GET "https://propertyinsights.co.uk/api/v1/planning/applications?address=14%20Example%20Avenue&postcode=ZZ1%201ZZ" \
  -H "x-api-key: YOUR_API_KEY"

Example response

{
  "success": true,
  "beta": true,
  "data": {
    "input": {
      "mode": "address",
      "address": "14 Example Avenue",
      "postcode": "ZZ1 1ZZ",
      "latitude": 52.123,
      "longitude": -1.234,
      "radiusM": 250
    },
    "coverage": {
      "status": "covered",
      "ladCode": "E00000001",
      "authority": "Exampleton District Council",
      "earliestReceivedDate": "2015-01-01",
      "lastCollectedAt": "2026-10-26T06:00:00.000Z",
      "message": "Applications received before earliestReceivedDate, or published after lastCollectedAt, may be missing."
    },
    "count": 1,
    "matchBasis": "Text and location based: house number or name and street are compared with the application address. Applications are not linked to UPRNs.",
    "applications": [
      {
        "id": "exampleton:24-00123-FUL",
        "reference": "24/00123/FUL",
        "authorityName": "Exampleton District Council",
        "address": "14 Example Avenue, Exampleton ZZ1 1ZZ",
        "postcode": "ZZ1 1ZZ",
        "proposal": "Single storey rear extension",
        "applicationType": "Full planning permission",
        "status": "Decided",
        "outcome": "approved",
        "lifecycle": "decided",
        "receivedDate": "2024-03-04",
        "validatedDate": "2024-03-11",
        "decisionDate": "2024-05-02",
        "latitude": 52.1231,
        "longitude": -1.2342,
        "distanceM": 12,
        "sourceUrl": "https://planning.exampleton.gov.example/applications/24-00123-FUL",
        "match": "property"
      }
    ],
    "nextCursor": null
  },
  "attribution": {
    "source": "Local planning authority public registers, collected by Property Insights",
    "notice": "Source material belongs to the publishing council. Follow each sourceUrl to the council record. Documents are linked, not copied."
  }
}

OpenAPI specification

Authentication, parameters, billing headers and response schemas are also published in the machine-readable OpenAPI documents in JSON and YAML.