Developer guides / Python · Published 9 September 2026 · By PlanWire

Search UK planning applications in Python

Make one council search, inspect the returned records and decide whether the data fits your product. Python 3.10 or later; no third-party packages.

Source and tests on GitHubOpen in PostmanCollection JSONResponse schema

1. Choose a council and an evaluation key

Create a free sample key, then choose a council ID from the coverage directory. This example uses richmond-thames. Free keys provide limited, potentially older samples, not a complete view of current applications. Live access and webhooks require an appropriate paid plan.

Set PLANWIRE_API_KEY in your local or server environment using your normal secret manager or private terminal session. Never put the key in a URL, repository, shared Postman value, screenshot or browser-side JavaScript. Avoid commands that leave real keys in shell history.

2. Run the bounded search

git clone https://github.com/beshogun/planwire-planning-search-example.git
cd planwire-planning-search-example
python3 search.py richmond-thames

The complete Python source makes this request, with your key in the X-API-Key header:

GET https://api.planwire.io/v1/applications?council=richmond-thames&limit=5
Accept: application/json
X-API-Key: YOUR_LOCAL_KEY

It requests at most five records, uses a 15-second socket timeout, rejects redirects and caps response size at 2 MB. It does not automatically retry or fetch more pages. The timeout is a socket-operation limit, not a guarantee of total wall-clock duration.

From your own Python code, call the same tested function:

import os
from search import search_council

response = search_council(
    os.environ["PLANWIRE_API_KEY"], council="richmond-thames"
)
for record in response["data"]:
    print(record.get("id"), record.get("description"))

3. Inspect evidence before counting opportunities

The script prints the returned JSON, including data and any meta fields. Keep that output private: the example code's MIT licence does not grant rights to republish API data. Check the data-use terms.

Planning permission is not evidence of a construction start or confirmed materials demand. This example evaluates data access; it is not a finished lead-generation product.

4. Handle errors and run the tests

The script exits with status 1 on failure. HTTP 401 points to authentication, 403 to access restrictions and 429 to your allowance or rate limit. Do not run a tight retry loop. For a timeout or server error, check connectivity and API status before deciding when to retry.

python3 -m unittest discover -p 'test_*.py' -v

The tests use synthetic responses without a key or network access. They check populated and empty samples, request parameters, authentication headers, bad inputs, HTTP errors, invalid JSON, size limits and redirect refusal. They do not establish live council completeness.

Prefer Postman for the first request?

Import the PlanWire UK Planning API collection into your own workspace. Set apiKey as a local, unshared environment variable and set Postman's request timeout to 15000 ms. Leave all shared credential values empty.

Run search or coverage first. For record lookup, use a returned ID as local applicationId; access depends on your plan. Recovery needs your existing paid webhook's ID as local webhookId. All four requests are read-only; nothing registers a webhook or sends a campaign.

Next: keep a cache updated with signed webhooks

After checking data suitability, use the signed webhook delivery and recovery guide and runnable monitoring-cache example. Verify signatures over the raw body, persist events durably and deduplicate by event ID.

On recovery, store the complete page before saving meta.nextCursor. Continue while meta.hasMore; do not advance a recovery cursor from an out-of-order delivery. The Postman request deliberately leaves the cursor unchanged.

The recovery stream starts with durable capture for that subscription, not earlier historical changes. Events are retained for at least 30 days while the webhook exists; deleting the webhook deletes its stream. See the recovery contract before building production ingestion.

Evaluate your actual workload

Get a sample key, check your councils, then choose access based on the records, request volume and update workflow your software needs. This is a PlanWire reference example, not a customer case study or a maintained Python SDK.