scotcourts
Search Scottish court cases via the undocumented scotcourts.gov.uk web API (judgments since 1999, fatal accident inquiry determinations). Use when the user asks to find/search Scottish judgments or opinions by keyword, court, or date, needs a scotcourts.gov.uk judgment PDF, or wants to check what Scottish authority exists on a point. Search results are LEADS only — reporting and citation follow the case-law skill standards (big red warning, confirmed paragraph pinpoints, verbatim chunks). Self-learning: appends lessons to learnings.md.
Source: .opencode/skills/scotcourts/SKILL.md — site rebuilt 2026-09-05.
SCTS Case Search (undocumented web API)¶
The SCTS public site's judgment search is a Vue SPA whose backend is an undocumented Azure autorest API. The API is public — no key, no auth — and is the only machine-readable way to search scotcourts.gov.uk.
API reference (reverse-engineered)¶
- Base URL:
https://api.pa.web.scotcourts.gov.uk/web(envSCTS_API_BASEoverrides; the client defaulthttps://api.dv.web.scotcourts.gov.uk/webis the dev host) GET /definition/{contentId}— widget config: configurations, filter fields, dropdown options, limitPOST /search— the search; body:Headers:{ "query": "…", "filters": [{"field": "Court", "value": "…"}], "page": 1, "limit": 50, "indexType": "Judgments", "category": "" }Accept: application/json,Content-Type: application/json; charset=utf-8.indexTypemust be the config'stype—"Unknown"or missing returns 400.- Date-range filter value serializes as
"YYYY-MM-DD|YYYY-MM-DD"(either side empty) - Response:
{results: […], pagination: {count: {total,start,end}, page: {current,total,limit}}}; each result:title,documentLink(relative — prefixhttps://www.scotcourts.gov.uk),date,court[],sheriffdom[],judges[],tags[] - Widgets: 1414 = Judgments (indexType
Judgments; filters Court/Date/AdditionalDate; limit 50; from 1999). 1363 = FAI Determinations (indexTypeFatalAccidentInquiryDeterminations; filters Sheriffdom/Date/AdditionalDate; limit 12)
Tooling¶
tools/scotcourts_search.py wraps the API:
python <skill>/tools/scotcourts_search.py search --query "<kw>" [--court "Court of Session"] [--date-from YYYY-MM-DD --date-to YYYY-MM-DD] [--page N] [--limit N] [--json]— judgments search (default widget).--content-id fai/--content-id 1363switches to determinations; FAI uses--sheriffdominstead of--court.… definition [--content-id N]— list a widget's config (courts/sheriffdoms as filter options)… download "<documentLink>" -o out.pdf— fetch the judgment PDF
Workflow¶
- State the legal issue the user needs authority on (case-law skill retrieval protocol step 1).
- Run
searchwith keyword (searches title AND narrative) and/or court/date filters. Pagination:page.totaltells you if there's more. - For each promising lead:
downloadthe PDF, OCR/map it per the okf-ocr skill if scanned or dense (adjudications/FAI determinations are dense — runtools/dense_doc_map.pybefore capturing holdings). - Reporting is the case-law skill's job. Every case returned to the user follows the case-law format: the big red warning verbatim, ISSUES DECIDED, per-issue HOLDINGS with confirmed paragraph pinpoints and verbatim
[N-1][N][N+1]chunks, positions-vs-holdings distinguished,[UNVERIFIED]flags where a pinpoint is not yet confirmed. The API gives you leads + PDFs, not authority — a title and date from the API is[UNVERIFIED]until the judgment text is read and pinpointed.
Gotchas¶
indexTypeis required and must match the config type (400 otherwise) — the tool sets it from the definition automatically.limitabove the widget's configured limit is clamped server-side (50 for judgments).- Results have no neutral citations or paragraph numbers — citations come from reading the PDF.
- The site also has
/geocode,/gazetteer,/locationsendpoints used by the court locator — not needed for case search.
Self-learning¶
learnings.md sits next to this SKILL.md. Read it before searching; append dated lessons after (API quirks, filter behaviours, widget changes). Never delete old entries.