GRANSKA

Search a jurisdiction's laws

GEThttps://api.granska.cloud/v1/laws

Searches a jurisdiction's catalogue of laws, and says which of them this corpus holds.

Bearer tokenSpends no quota

What this answers that a public register does not

You can find an SFS number on riksdagen.se. What you cannot find there is whether a citation to it will resolve here — and that is the one thing a profile needs to be accepted.

That is the held field on every hit. true means the law is in the library and POST /v1/profiles will accept a reference to it. false means it is not, yet.

Searching is free. It spends no analysis quota and counts against no floor, so you may call it as often as your integration needs. That is deliberate: a caller who cannot search cheaply guesses citations instead, against a metered write endpoint, and that is worse for everyone.

Request
curl -G https://api.granska.cloud/v1/laws \
  --data-urlencode "jurisdiction=SE" \
  --data-urlencode "query=föräldrabalk" \
  -H "Authorization: Bearer $TOKEN"
Response
{
  "jurisdiction": "SE",
  "fetchable": true,
  "attribution": null,
  "unavailableSources": [],
  "laws": [
    {
      "jurisdiction": "SE",
      "work": "1949:381",
      "title": "Föräldrabalk (1949:381)",
      "displayLabel": "Föräldrabalk (1949:381)",
      "pinpoint": null,
      "issuingBody": "Justitiedepartementet L2",
      "repealedAt": null,
      "held": true
    },
    {
      "jurisdiction": "SE",
      "work": "1981:1292",
      "title": "Förordning (1981:1292) om vårdnadsutredningar",
      "displayLabel": "Förordning (1981:1292) om vårdnadsutredningar",
      "pinpoint": null,
      "issuingBody": "Justitiedepartementet",
      "repealedAt": null,
      "held": false
    }
  ]
}

The parameters

jurisdiction says which legal order to search. SE, NO, DK and US_FED resolve today. Any other value is refused with a 400 that names what is available — never an empty list, because an empty list would say that law does not exist when the truth is we have not integrated that country.

US_FED is answered by two sources at once, and the answer takes one hit from each in turn — regulations first — so a small limit narrows both halves rather than cutting one of them away. Federal regulations come from the Office of the Federal Register's own full-text search of the Code of Federal Regulations, live on every request, so a regulation is searchable from the first day; a hit is a CFR part, such as 45 CFR 1355. Federal statutes come from a catalogue of the United States Code that is rebuilt nightly from the release point the Office of the Law Revision Counsel publishes, so that half of the answer is empty until the first corpus night after the integration has run, and a section Congress adds appears the night after the release point carrying it does.

query is matched against each law's number and its title. Two characters minimum. A shorter query is a 400 rather than a list of everything.

unavailableSources names, by source id, a law source that did not answer while another did. It is [] on the ordinary day. US_FED is the case it exists for: the regulations half is a live call to the Office of the Federal Register, and when that service refuses under load the statutes half, which reads our own copy, still answers — the response then carries "unavailableSources": ["us-ecfr"] beside the hits it has, so an absent CFR hit can be told from a CFR that was not asked. The two ids US_FED can name are us-ecfr for the regulations and us-uscode for the statutes; compare against those exact strings. Retry for the full list. A search that every source fails is a 500, never an empty list.

ParameterDescription
jurisdiction
string·query·required
Which legal order to search, as a code such as SE. Only a legal order with an integrated law source can be searched — SE, NO, DK and US_FED resolve today; anything else is refused by name.
query
string·query·required
Free text matched against each law's number and title. At least two characters.
limit
integer·query
How many hits to return, between 1 and 50. Defaults to 50.
{
  "jurisdiction": "SE",
  "fetchable": true,
  "attribution": null,
  "unavailableSources": [],
  "laws": [
    {
      "jurisdiction": "SE",
      "work": "1949:381",
      "displayLabel": "Föräldrabalk (1949:381)",
      "pinpoint": null,
      "held": true
    }
  ]
}

pinpoint — when a hit names a provision rather than a law

Most catalogues are catalogues of laws. Search Sweden, Norway or Denmark and a hit is an act, and pinpoint is null because there is no provision in the row to name.

Search the Code of Federal Regulations and a hit is a part, such as 45 CFR 1355, and pinpoint is null there for a different reason: eCFR searches at section level, and we fold those hits to their parts because a part is what an agency amends as a piece. The section exists in the hit; we do not offer it. Read null as "this hit names no provision", not as a promise that a catalogue never will.

The United States Code is the other shape. Its catalogue is built one section at a time, so 42 U.S.C. 1983 answers with § 1983 itself rather than with the 8 481-section title it sits in. That hit carries the section as data:

{
  "jurisdiction": "US_FED",
  "work": "42 U.S.C.",
  "pinpoint": "§ 1983",
  "displayLabel": "42 U.S.C. § 1983 — Civil action for deprivation of rights",
  "held": true
}

work and pinpoint are exactly the two fields POST /v1/profiles wants in a reference, in exactly the spelling it wants them. Send them back as they arrived — searching for a section and citing it is two calls, and nothing in between is composed or taken apart.

Do not parse a pinpoint out of displayLabel. The label is prose formatted for a reader, and the § 1983 inside it is there to be read, not to be extracted. Where pinpoint is null and you need a provision, read the law itself with GET /v1/laws/:jurisdiction/:work, which carries the pinpoint of every provision it returns.

Two title fields, and which one to show

displayLabel is the one to put in front of a person. It is a single clean line, formatted for that purpose.

title is the register's own text, untouched — which means hard line breaks inside it, the law's number repeated within it, and several lines of it on older acts. It is published because it is the authentic wording and some integrations need exactly that. It is not published because it is presentable.

We do not publish an instrument type — whether something is a lag, a förordning or a författning — as a separate field, and we will not add one. The Swedish register does not state it: every row of it is labelled SFS, which names the register rather than the kind of instrument. The only way to produce that field would be to guess it from the first word of a Swedish title, and a legal fact inferred from a text string is not a legal fact. A reader still sees it, because displayLabel reads "Förordning (1982:47) om…". We show it; we never assert it.

repealedAt is a date when the law has been repealed and null when it has not. A repealed law is still returned and still citable — that is a judgment for you to make, not one for a search endpoint.

attribution is a licence condition, not a courtesy

Some registers are licensed data, and the licence requires that the source be named wherever the data is shown. attribution carries the exact line that register demands, and it is null where no such duty exists.

Norway's catalogue is published by Stiftelsen Lovdata under NLOD 2.0, so a Norwegian search answers:

{
  "jurisdiction": "NO",
  "fetchable": true,
  "attribution": "Inneholder data under Norsk lisens for offentlige data (NLOD) tilgjengeliggjort av Stiftelsen Lovdata.",
  "unavailableSources": [],
  "laws": []
}

Sweden's register carries no such condition and always answers null.

Show the line wherever you show the data. The duty travels with the text: it reaches your product the moment you display a Norwegian title or provision to a user, and passing the data on without it is a breach of the licence we hold. Read the field rather than hardcoding the sentence — a register's required wording is theirs to change, and a hardcoded copy is one that silently stops being correct.

held: false means one of two things, and fetchable says which

fetchable sits on the response, not on each hit, because it is a fact about the jurisdiction's source rather than about any one law.

  • fetchable: true — ask for the law with GET /v1/laws/:jurisdiction/:work and it will be fetched, parsed and stored on the spot. held: false here means not yet. Sweden, Norway, Denmark and the United States all work this way.
  • fetchable: false — that jurisdiction's corpus arrives as whole bulk archives with no way to request a single law. held: false here means asking will not change it. What is absent stays absent until the next bulk refresh.

Errors

Every refusal here is a 400, and every one of them names what was wrong with the request. There is no 404: a search that matches nothing is a successful search with an empty laws array. A search that could not be performed at all is an error, and the two are never confused.

ErrorWhen
400
BAD_REQUEST
jurisdiction is missing or names no legal order with an integrated law source — being open is not enough, and the message names the ones that resolve — or query is missing or shorter than two characters, or limit is not a whole number between 1 and 50.
401
UNAUTHORIZED
The Authorization header is missing, is not a readable bearer token, or names no tenant.
401
TOKEN_EXPIRED
The access token was issued by this gateway and has since expired. Not probed: it needs a token older than its own lifetime.
500
INTERNAL_ERROR
An unexpected server-side failure. Not probable from outside — reaching it means something is wrong.

Send it without writing a client

If your organisation already has an account, an administrator can call this from the API tester at /admin/api-tester without spending any quota.