Search a jurisdiction's laws
https://api.granska.cloud/v1/lawsSearches a jurisdiction's catalogue of laws, and says which of them this corpus holds.
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.
curl -G https://api.granska.cloud/v1/laws \
--data-urlencode "jurisdiction=SE" \
--data-urlencode "query=föräldrabalk" \
-H "Authorization: Bearer $TOKEN"{
"jurisdiction": "SE",
"fetchable": true,
"laws": [
{
"jurisdiction": "SE",
"work": "1949:381",
"title": "Föräldrabalk (1949:381)",
"displayLabel": "Föräldrabalk (1949:381)",
"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",
"issuingBody": "Justitiedepartementet",
"repealedAt": null,
"held": false
}
]
}The parameters
jurisdiction says which legal order to search. SE and NO 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.
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.
| Parameter | Description |
|---|---|
jurisdictionstring·query·required | Which legal order to search. SE and NO resolve today; anything else is refused by name. |
querystring·query·required | Free text matched against each law's number and title. At least two characters. |
limitinteger·query | How many hits to return, between 1 and 50. Defaults to 50. |
{
"jurisdiction": "SE",
"fetchable": true,
"attribution": null,
"laws": [
{
"jurisdiction": "SE",
"work": "1949:381",
"displayLabel": "Föräldrabalk (1949:381)",
"held": true
}
]
}
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.",
"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 withGET /v1/laws/:jurisdiction/:workand it will be fetched, parsed and stored on the spot.held: falsehere means not yet. Both Sweden and Norway work this way.fetchable: false— that jurisdiction's corpus arrives as whole bulk archives with no way to request a single law.held: falsehere 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.
| Error | When |
|---|---|
400BAD_REQUEST | jurisdiction is missing or is not one this API carries, query is missing or shorter than two characters, or limit is not a whole number between 1 and 50. |
401UNAUTHORIZED | The Authorization header is missing, is not a readable bearer token, or names no tenant. |
401TOKEN_EXPIRED | The access token was issued by this gateway and has since expired. Not probed: it needs a token older than its own lifetime. |
500INTERNAL_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.