API reference

Agent-friendly: this page as Markdown → /docs.md

Base URL https://lawapi.app/api/v1. Every response is an AFDATA v1 envelope: {"kind":"result","result":…,"trace":{}} on success, {"kind":"error","error":…} otherwise. Text comes back in the language the official source published it in; the API never translates or paraphrases the record.

GET /api/v1/search

Full-text search over provisions in all 37 jurisdictions. Query in any language the sources use; results rank by relevance across works and sections.

ParameterTypeNotes
qstringRequired. Words are ANDed; a multi-word query that finds nothing is widened to OR. Quote a phrase to keep it whole.
jurisdictionstringOptional. One of the codes below. Omit to search everything.
limitintegerOptional. 1–100, default 20.
curl 'https://lawapi.app/api/v1/search' -G \
  --data-urlencode 'q=解雇の予告' \
  --data-urlencode 'jurisdiction=jp' \
  --data-urlencode 'limit=1'
{
  "kind": "result",
  "result": {
    "query": "解雇の予告",
    "result_count": 1,
    "results": [
      {
        "id": "wq_jp_5b89e4a20f42e4c9#article-20",
        "jurisdiction": "jp",
        "work": {
          "title": "労働基準法",
          "slug": "law-0091651e1f",
          "legal_force": "in_force",
          "source_urls": ["https://laws.e-gov.go.jp/law/322AC0000000049"]
        },
        "section": {
          "ref": "article-20",
          "num_label": "第二十条",
          "heading_path": "第二章 労働契約",
          "language": "ja",
          "is_authoritative": false,
          "untranscribed_graphic_count": 0,
          "text": "使用者は、労働者を解雇しようとする場合においては、少くとも三十日前にその予告をしなければならない。…"
        },
        "url": "https://laws.e-gov.go.jp/law/322AC0000000049"
      }
    ]
  },
  "trace": {}
}

Response contract

Each element of results is one provision. Identifiers are stable across calls; id is <work id>#<section ref>.

FieldMeaning
jurisdictionJurisdiction code, the same value you can pass as a filter.
work.titleTitle of the act or regulation as published.
work.legal_forcein_force · repealed · expired · not_yet_in_force · unknown. Computed at query time from the dates the source states; unknown when it states none.
work.source_urlsOfficial publication URLs for the work. url on the hit is the first of them.
section.refStable section reference inside the work.
section.num_labelThe label to cite, in the source's own convention.
section.heading_pathPart / chapter / heading trail, joined with / . Empty when the act has no structure above the section.
section.languageBCP 47 tag of section.text.
section.is_authoritativetrue when this text is the legally binding version; false for official translations and for sources that publish consolidated text without asserting authority.
section.untranscribed_graphic_count0 for a verbatim-complete provision. Greater than zero means part of the provision is published only as a figure, formula or table and its content is not in section.text: the text carries an explicit in-place editorial marker (or the publisher's own "graphic only" wording) at that position. Go to work.source_urls for the graphic itself.
section.textThe provision as published. Plain text for most sources; sources that publish rich gazette markup (UK, Canada, Australia, France) keep it as HTML with the publisher's own attributes, so render or strip it deliberately.

Jurisdictions

GET /api/v1/jurisdictions

Every jurisdiction with its primary language and published-law count. Free; does not consume credits. Codes currently in the index:

{
  "kind": "result",
  "result": {
    "jurisdictions": [
      { "code": "au", "name": "Australia", "primary_language": "en", "law_count": 23113 },
      { "code": "de", "name": "Germany",   "primary_language": "de", "law_count": 5959 },
      …
    ]
  },
  "trace": {}
}

Errors

Errors use kind: "error" with a machine-readable code, a human-readable message, a retryable flag and, where there is an obvious next step, a hint. HTTP status matches: 400 for a bad request, 401 for an invalid key, 429 when rate-limited, 5xx when it is our fault.

{
  "kind": "error",
  "error": {
    "code": "unauthorized",
    "message": "invalid API key",
    "retryable": false,
    "hint": "send Authorization: Bearer <api_key>; get a free key at https://lawapi.app/pricing"
  },
  "trace": {}
}

MCP

POST /mcp

A Model Context Protocol server over JSON-RPC 2.0 — initialize, tools/list, tools/call — exposing one search tool with the same parameters and result shape as the REST endpoint. Point any MCP client at it:

{
  "mcpServers": {
    "lawapi": {
      "url": "https://lawapi.app/mcp",
      "headers": { "Authorization": "Bearer lawapi_…" }
    }
  }
}

Auth

Send your key as a bearer token. During the beta, requests without a key are allowed at the anonymous rate limit; a request with an invalid key is always rejected with 401, so a typo never silently downgrades you.

curl 'https://lawapi.app/api/v1/search?q=redundancy&jurisdiction=ie' \
  -H 'Authorization: Bearer lawapi_…'

Limits

Rate limits are per key, or per IP without one: 60 requests per minute on the free tier, 120 on pay as you go. limit caps at 100 results per call. There is no pagination yet; narrow with jurisdiction and a more specific q instead.