GRANSKA

List or resolve legal sources

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

Lists the legal sources this tenant may use, or resolves exactly one of them.

Bearer tokenSpends no quota

Two modes, and they are mutually exclusive

Send no query parameters and you get the list: every legal source your tenant may cite, both the shared ones and any your organisation authored itself. Add includeText=true and each entry carries its body as well as its metadata.

Name a source and you get that one source instead, projected down to six fields. There are two ways to name one, and they cannot be combined:

  • snippetKey — the stable key of an authored source.
  • jurisdiction + work + pinpoint — a provision of published law, given as three separate fields.

A request carrying snippetKey together with any of the reference fields is a 400. So is a reference missing any of its three parts. The endpoint never guesses which kind of identifier you have, because the two are governed by different authorities and a wrong guess would answer with the wrong law — and the caller always knows: a delivered analysis states both explicitly beside each citation.

This is the lookup behind a clickable citation in a report. includeText applies to the list only.

Both modes start from an identifier you already have. To go the other way — from a subject to a law you could cite — search the catalogue with GET /v1/laws and read its provisions with GET /v1/laws/:jurisdiction/:work.

Request
# List everything this tenant may use:
curl "https://api.granska.cloud/v1/snippets" \
  -H "Authorization: Bearer $TOKEN"

# Or resolve exactly one provision. A pinpoint is the provision's node id, not its
# printed label, and it can carry characters that must be percent-encoded in a query
# string — let curl do it with -G --data-urlencode rather than pasting it raw:
curl -G "https://api.granska.cloud/v1/snippets" \
  --data-urlencode "jurisdiction=SE" \
  --data-urlencode "work=1993:387" \
  --data-urlencode "pinpoint=par_7§" \
  -H "Authorization: Bearer $TOKEN"
Response
{
  "snippets": [
    {
      "id": "snip_3f0a",
      "tenantId": "SYSTEM",
      "snippetKey": "lss-7-goda-levnadsvillkor",
      "name": "7 § LSS — goda levnadsvillkor",
      "source": "SFS 1993:387",
      "authorityType": "STATUTE",
      "validFromYear": 1994,
      "validToYear": null,
      "updatedAt": {
        "_seconds": 1781164800,
        "_nanoseconds": 0
      },
      "normLevel": "Lag",
      "legalWeight": "BINDING"
    }
  ]
}

Naming one source

Note that any one of jurisdiction, work or pinpoint switches the endpoint into single-source mode. A stray ?work= on a call you meant as a list is therefore a 400 rather than a list — the endpoint would otherwise have to decide silently that you did not mean it.

Never assemble the three parts into a key string like SE/2009:400/kap_26_par_1§ and send that. The projection to such a string is one-way by design and has no inverse; it exists so the database can index on it, not so it can be read back.

Treat work and pinpoint as opaque: never parse them, pattern-match on them or split them. Their shape differs per jurisdiction and is not part of the contract — see the anchor fields.

ParameterDescription
includeText
"true" | "false"·query
Set to "true" to get each source's full text rather than metadata alone.
snippetKey
string·query
Resolves the one authored source with this key instead of listing. Cannot be combined with the reference fields.
jurisdiction
string·query
Which legal order the provision belongs to. Given together with work and pinpoint, resolves one statute provision.
work
string·query
Which law. Given together with jurisdiction and pinpoint, resolves one statute provision.
pinpoint
string·query
Where in the law — the id the provision is addressed by ("par_7§"), never the label it is printed as ("7 §"). Given together with jurisdiction and work, resolves one statute provision.
{
  "snippet": {
    "name": "Barnets bästa",
    "source": "SoL 5 kap. 1 §",
    "content": "När åtgärder rör barn ska barnets bästa särskilt beaktas...",
    "authorityType": "STATUTE",
    "validFromYear": 2024,
    "validToYear": null
  }
}

What the list returns, and what it no longer returns

The list is a fixed field list, not the stored document: id, tenantId, snippetKey, name, source, authorityType, validFromYear, validToYear and updatedAt, plus text, content and anchors when includeText=true. An internal field added to the database tomorrow cannot appear in your response, which used to be exactly what happened.

Two fields in the list are deprecatednormLevel and legalWeight. They are no longer stored; they are computed on the way out so that nobody had to migrate in the same release as the rename. Read Deprecated fields before using either, and read authorityType instead.

The single-source response carries neither. That mode was introduced with the new names, so there is no client with an old expectation to keep — and what was never published never needs deprecating.

validFromYear and validToYear are display metadata only. Nothing in the engine selects a version by them.

updatedAt is stamped when a source is written, is absent on sources that have never been rewritten since import — that is not a fault — and is serialised as a raw database timestamp rather than ISO 8601, the same quirk as on GET /v1/jobs/:jobId.

Errors

404 does not distinguish "no such source" from "not yours". A key belonging to another organisation answers exactly as a key that never existed, so this endpoint cannot be used to probe what anyone else holds.

ErrorWhen
400
BAD_REQUEST
snippetKey was combined with a reference field, or a reference was given without all three of jurisdiction, work and pinpoint.
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.
404
NOT_FOUND
No source matches, or none this tenant may see. The gateway does not distinguish the two.
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 browse the catalogue from the API tester at /admin/api-tester without spending any quota.