Crime API Reference
Monthly street-level crime and outcome data published by Police.uk.
Base URL: https://api.govdata.dev/v1
Search crime
Returns paginated, newest-first street-level crime records for analysts, civic-data teams, and local publishers. Combine month, category, force, and LSOA filters to power an LSOA-level community safety dashboard or compare recorded public-order incidents across police forces.
/v1/crime
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
month |
string | No | — | Recorded month in YYYY-MM format. |
category |
string | No | — | Exact category label returned by GET /v1/crime/categories. |
force |
string | No | — | Lowercase Police.uk force slug, for example city-of-london-police. |
lsoa_code |
string | No | — | 2021 Lower Layer Super Output Area code; matching is case-insensitive. |
page |
integer | No | 1 | One-based result page. |
per_page |
integer | No | 25 | Results per page; minimum 1, maximum 100. |
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.govdata.dev/v1/crime?month=2026-06&category=Public%20order&force=city-of-london-police&lsoa_code=E01000914&per_page=2"
uri = URI("https://api.govdata.dev/v1/crime") uri.query = URI.encode_www_form(month: "2026-06", category: "Public order", force: "city-of-london-police", lsoa_code: "E01000914", per_page: 2) req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get( "https://api.govdata.dev/v1/crime", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"month": "2026-06", "category": "Public order", "force": "city-of-london-police", "lsoa_code": "E01000914", "per_page": 2} )
const url = new URL("https://api.govdata.dev/v1/crime"); url.search = new URLSearchParams({ month: "2026-06", category: "Public order", force: "city-of-london-police", lsoa_code: "E01000914", per_page: "2" }); const response = await fetch(url, { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": [ { "persistent_id": "372dea2f064aa7d5cb035b7bed79cc16a3b4de05dc3bc782dd22058a0f87d004", "month": "2026-06", "category": "Public order", "force": "city-of-london-police", "force_name": "City of London Police", "longitude": -0.111596, "latitude": 51.518281, "location": "On or near Chancery Lane", "location_precision": "Approximate anonymised location", "lsoa_code": "E01000914", "lsoa_name": "Camden 028B", "last_outcome_category": "Under investigation", "context": null } ], "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "Police.uk", "source_url": "https://data.police.uk/data/" }, "pagination": { "total": 1, "page": 1, "per_page": 2, "total_pages": 1 } }
longitude and latitude identify Police.uk's anonymised snap-point, not the incident site. lsoa_code and lsoa_name describe that snapped location. The example uses real LSOA E01000914 from the bundled Police.uk development fixture.
Error responses
400 — malformed month. Search has no record-specific 404 or semantic 422 branch; valid filters with no matches return an empty 200 response.
{"error":{"code":"invalid_parameter","message":"month must be YYYY-MM.","documentation_url":"https://docs.govdata.dev/errors/invalid_parameter"}}
Crime categories
Returns the distinct category labels currently present in GovData, for developers building filter menus or validating category values before a crime search. Use it to populate a community-safety widget without hard-coding Police.uk's vocabulary.
/v1/crime/categories
No parameters required.
Waiting for request...
Parameters
| Name | Type | Required | Default | Description |
|---|
This endpoint has no path, query, or pagination parameters.
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.govdata.dev/v1/crime/categories"
uri = URI("https://api.govdata.dev/v1/crime/categories") req = Net::HTTP::Get.new(uri, "Authorization" => "Bearer YOUR_API_KEY") res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
response = requests.get("https://api.govdata.dev/v1/crime/categories", headers={"Authorization": "Bearer YOUR_API_KEY"})
const response = await fetch("https://api.govdata.dev/v1/crime/categories", { headers: { Authorization: "Bearer YOUR_API_KEY" } });
Response
{ "data": ["Anti-social behaviour", "Burglary", "Public order", "Robbery", "Vehicle crime", "Violence and sexual offences"], "meta": { "api_version": "v1", "licence": "Open Government Licence v3.0", "source": "Police.uk", "source_url": "https://data.police.uk/data/" } }
This is a data-driven list, so labels appear only when the loaded coverage contains at least one record in that category.
Error responses
There are no endpoint-specific 400, 404, or 422 responses because the endpoint accepts no parameters; an empty dataset returns data: [] with HTTP 200.
Data notes
Coverage and cadence: monthly street-level records for participating police forces in England, Wales and Northern Ireland. Police.uk normally publishes each month with an approximately two-month lag; GovData imports the monthly bulk archive after publication. Scotland is not covered by Police.uk street-level data.
Licence and attribution: source Police.uk bulk data, licensed under the Open Government Licence v3.0. Attribute Police.uk when republishing.
Police.uk anonymises locations to nearby snap-points; coordinates are not exact incident locations and an LSOA describes the anonymised point. This is operational police data and is not official statistics. Recording, geocoding, and outcome practices vary between forces, and later publications may revise records.
Some source rows have a blank Crime ID. GovData returns persistent_id: null and uses a deterministic digest only for internal deduplication. Byte-identical blank-ID incidents can therefore merge, and blank-ID crimes cannot be linked to outcomes.