Health — entry 020 of 23
Open Data NHS Scotland
Public Health Scotland's open-data portal is a keyless CKAN instance covering GP practices, prescribing, hospital admissions, and population health statistics for Scotland, queryable via the standard CKAN Action API (datastore_search, datastore_search_sql) with no registration. A live GET against the site's api/3/action endpoints succeeds without a key. A live Origin-header probe (both a plain GET and an OPTIONS preflight) against the same host returns no Access-Control-Allow-Origin header, so the stored 'unknown' cors resolved to 'no'.
Public Health Scotland's open-data portal is a keyless CKAN instance covering GP practices, prescribing, hospital admissions, and population health statistics for Scotland, queryable via the standard CKAN Action API (`package_show`, `datastore_search`, `datastore_search_sql`) with no registration. A live GET against `datastore_search` this run succeeded without a key and returned a real GP-practice record; both a plain GET and an OPTIONS preflight with an `Origin` header returned no `access-control-allow-origin` header at all, confirming the stored `cors: no`.
GreatAPIs Score
Auth quickstart
- No API key required. Every action is a GET (or POST) against `/api/3/action/<action_name>` with query params -- confirmed live this run against `package_show` and `datastore_search`.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
Query one record from a GP-practice datastore resource
GEThttps://www.opendata.nhs.scot/api/3/action/datastore_search?resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8&limit=1
{"help": "https://www.opendata.nhs.scot/api/3/action/help_show?name=datastore_search", "success": true, "result": {"include_total": true, "resource_id": "0032ce94-f7f6-44dd-879c-7d3074d8e2e8", "fields": [{"type": "int", "id": "_id"}, {"type": "numeric", "id": "PracticeCode"}, {"type": "text", "id": "GPPracticeName"}, {"type": "numeric", "id": "PracticeListSize"}, {"type": "text", "id": "AddressLine1"}, {"type": "text", "id": "AddressLine2"}, {"type": "text", "id": "AddressLine3"}, {"type": "text", "id": "AddressLine4"}, {"type": "text", "id": "Postcode"}, {"type": "text", "id": "TelephoneNumber"}, {"type": "text", "id": "PracticeType"}, {"type": "text", "id": "HB"}, {"type": "text", "id": "HSCP"}, {"type": "text", "id": "DataZone"}, {"type": "text", "id": "GPCluster"}], "records_format": "objects", "records": [{"_id":1,"PracticeCode":10002,"GPPracticeName":"Muirhead Medical Centre","PracticeListSize":8559,"AddressLine1":"Muirhead Medical Centre","AddressLine2":"Liff Road","AddressLine3":"Muirhead","AddressLine4":"","Postcode":"DD2 5NH","TelephoneNumber":"01382 580 264","PracticeType":"GMS","HB":"S08000030","HSCP":"S37000007","DataZone":"S01007129","GPCluster":"Dundee 4"}], "limit": 1, "_links": {"start": "/api/3/action/datastore_search?limit=1&resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8", "next": "/api/3/action/datastore_search?offset=1&limit=1&resource_id=0032ce94-f7f6-44dd-879c-7d3074d8e2e8"}, "total": 879}}Developer reference
https://www.opendata.nhs.scot/api/3/action/Gotchas & limits
- `resource_id` values are tied to a specific quarterly CSV upload, not a stable long-lived identifier for "the current GP practice list": the id pinned above (`0032ce94-f7f6-44dd-879c-7d3074d8e2e8`) is this run's July 2026 release -- a live `package_show?id=gp-practice-contact-details-and-list-sizes` this run listed a fresh `resource_id` for every quarter back to 2018, so re-discover the current one via `package_show` before hardcoding it.
- An invalid `resource_id` is a real HTTP 404 with a CKAN error envelope, not a 200: a live `datastore_search?resource_id=00000000-0000-0000-0000-000000000000` this run returned `{"success": false, "error": {"message": "Not found: Resource \"00000000-0000-0000-0000-000000000000\" was not found.", "__type": "Not Found Error"}}` at status 404 -- check both the HTTP status and `success` before reading `result`.
- The SQL variant `datastore_search_sql` is enabled and equally keyless: a live `SELECT * FROM "<resource_id>" LIMIT 1` against the same resource this run returned 200 with a `success: true` envelope and the matching row -- useful for filters CKAN's own `datastore_search` query params can't express, but it accepts arbitrary read-only SQL, so treat it as a public read replica rather than a locked-down endpoint.
- No CORS support at all, even for preflight: a live `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers this run returned HTTP 200 with `Allow: HEAD, GET, POST, OPTIONS` but no `access-control-allow-origin` or any other CORS response header -- browser-side calls need a server-side proxy.