API Reference

Complete reference for the Moonlit Data API. Search across all 30 European jurisdictions, retrieve full texts, and use the reference graph.

Try requests live in the interactive Swagger docs.

Base URL

https://api.moonlit.ai/v1.1

Authentication

Ocp-Apim-Subscription-Key

Pricing & limits

see FAQ

Response Format

JSON

Authentication

All API requests must include your subscription key in the Ocp-Apim-Subscription-Key header. Request your key here.

Keep your API key secret. Do not expose it in client-side code or public repositories. If your key is compromised, contact our team immediately.

curl -X POST "https://api.moonlit.ai/v1.1/search/keyword_search" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY" \
  -d '{"query": "huurrecht opzegging", "jurisdictions": ["Netherlands"]}'

Base URL

All API endpoints are relative to the following base URL:

https://api.moonlit.ai/v1.1

For example, the keyword search endpoint is available at https://api.moonlit.ai/v1.1/search/keyword_search.

Errors

The API uses standard HTTP status codes to indicate the success or failure of a request. Codes in the 2xx range indicate success, 4xx indicate a client error, and 5xx indicate a server error.

Status CodeMeaningDescription
400Bad RequestThe request body is malformed or missing required parameters.
401UnauthorizedThe API key is missing or invalid.
403ForbiddenYour API key does not have permission to access this resource.
422Validation ErrorThe request body failed validation. Check required fields and parameter types.
429Rate LimitedYou have exceeded your monthly request quota. Contact our team to discuss your plan.
500Server ErrorAn unexpected error occurred on our end. Try again or contact support if the issue persists.
504Gateway TimeoutThe search timed out. This can happen with complex hybrid or semantic queries. Try narrowing your filters or reducing num_results.

Error response format:

{
  "error": {
    "code": 401,
    "message": "Invalid or missing API key."
  }
}

Which search should you use?

"I have a natural language question"

Hybrid Search (best default)

Need max precision? Add reranking

"I need exact terms, case numbers, Boolean logic"

Keyword Search

Sort by date or citations with sort_type

"I want concept-based discovery"

Semantic Search

Need max precision? Add reranking

"I just want answers, not document lists"

Luna API (streaming research assistant)

POST/v1.1/search/semantic_search_reranked

Semantic Search with Reranking

Same as semantic search but applies a reranker to the results for improved relevance. Uses Google Vertex AI reranking.

Parameters

ParameterTypeDescription
querystringNatural-language semantic query text.

Example Request

curl -X POST "https://api.moonlit.ai/v1.1/search/semantic_search_reranked" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "jurisdictions": [
    "European Union",
    "Netherlands"
  ],
  "query": "data transfer safeguards",
  "num_results": 10
}'

Example Response

{
  "result": {
    "count": 405,
    "skip": 0,
    "top": 10,
    "results": [
      {
        "identifier": "62018CJ0311",
        "secondaryIdentifier": "ECLI:EU:C:2020:559",
        "tertiaryIdentifier": "C-311/18",
        "portal": "eur-lex.europa.eu",
        "startDate": "2018-05-09T00:00:00+00:00",
        "endDate": "2020-07-16T00:00:00+00:00",
        "highlights": [
          "...<span class='bold'>data</span> <span class='bold'>privacy</span>..."
        ],
        "title": "Data Protection Commissioner/Facebook Ireland Limited and Maximillian Schrems (European Court of Justice 16 July 2020, C-311/18, ECLI:EU:C:2020:559)",
        "court": "European Court of Justice",
        "year": 2020,
        "sources": [
          {
            "id": "02045a9e2de3f3bd6c520ad0317efd0d",
            "parentId": "f7875ac0576a21c24937d480f6fde4f1",
            "shortName": "European Court of Justice",
            "name": "European Court of Justice"
          }
        ],
        "fieldsOfLaw": [
          {
            "id": "6c1022289490f6fca4adcf0e082d2524",
            "shortName": "European data protection law",
            "name": "European data protection law"
          }
        ],
        "documentTypes": [
          {
            "id": "04b42e5bf858a66de2229227deaa21e3",
            "shortName": "Decisions",
            "name": "Decisions"
          }
        ],
        "language": "EN",
        "dataSource": 0,
        "referenced": 165,
        "literatureReferenced": 103,
        "score": 24.674826,
        "sourceUrl": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:62018CJ0311"
      }
    ],
    "facets": {
      "DataSources": [
        {
          "shortName": "EU",
          "name": "European Union",
          "value": "0",
          "count": 128,
          "portals": [
            {
              "name": "eur-lex.europa.eu",
              "value": "0|eur-lex.europa.eu",
              "count": 59
            }
          ]
        }
      ],
      "Portals": [
        {
          "shortName": "eur-lex.europa.eu",
          "name": "eur-lex.europa.eu",
          "value": "eur-lex.europa.eu",
          "count": 59
        }
      ],
      "FieldsOfLaw": [
        {
          "shortName": "Public law",
          "name": "Public law",
          "value": "2f6b898befaa9e641cd8ee258cd8f22e",
          "count": 1,
          "tooltip": "Public law",
          "children": []
        }
      ],
      "DocumentTypes": [
        {
          "shortName": "Decisions",
          "name": "Decisions",
          "value": "04b42e5bf858a66de2229227deaa21e3",
          "count": 33,
          "tooltip": "Decisions",
          "children": []
        }
      ],
      "sources": [
        {
          "shortName": "International courts",
          "name": "International courts",
          "value": "f7875ac0576a21c24937d480f6fde4f1",
          "count": 30,
          "tooltip": "International courts",
          "children": []
        }
      ]
    }
  },
  "success": true
}
POST/v1.1/search/hybrid_search_reranked

Hybrid Search with Reranking

Same as hybrid search but applies a reranker to the fused results for improved relevance. Uses Google Vertex AI reranking. The reranker re-scores results after RRF fusion, giving higher-quality ranking at the cost of slightly higher latency. Filter values are validated server-side. Retrieve accepted values from the filter endpoints before applying them: - GET /v1.1/search/filters/documenttypes — accepted documentTypes IDs - GET /v1.1/search/filters/jurisdictions_portals — accepted jurisdiction names and portal values - GET /v1.1/search/filters/trees — accepted fieldsOfLaw IDs

Parameters

ParameterTypeDescription
querystringNatural-language query. The system extracts keyword terms automatically and runs both keyword and semantic searches in parallel, fusing the results.

Example Request

curl -X POST "https://api.moonlit.ai/v1.1/search/hybrid_search_reranked" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "jurisdictions": [
    "European Union",
    "Netherlands"
  ],
  "query": "What are the GDPR requirements for cross-border data transfers?",
  "num_results": 10,
  "semantic_weight": 0.6
}'

Example Response

{
  "result": {
    "count": 405,
    "skip": 0,
    "top": 10,
    "results": [
      {
        "identifier": "62018CJ0311",
        "secondaryIdentifier": "ECLI:EU:C:2020:559",
        "tertiaryIdentifier": "C-311/18",
        "portal": "eur-lex.europa.eu",
        "startDate": "2018-05-09T00:00:00+00:00",
        "endDate": "2020-07-16T00:00:00+00:00",
        "highlights": [
          "...<span class='bold'>data</span> <span class='bold'>privacy</span>..."
        ],
        "title": "Data Protection Commissioner/Facebook Ireland Limited and Maximillian Schrems (European Court of Justice 16 July 2020, C-311/18, ECLI:EU:C:2020:559)",
        "court": "European Court of Justice",
        "year": 2020,
        "sources": [
          {
            "id": "02045a9e2de3f3bd6c520ad0317efd0d",
            "parentId": "f7875ac0576a21c24937d480f6fde4f1",
            "shortName": "European Court of Justice",
            "name": "European Court of Justice"
          }
        ],
        "fieldsOfLaw": [
          {
            "id": "6c1022289490f6fca4adcf0e082d2524",
            "shortName": "European data protection law",
            "name": "European data protection law"
          }
        ],
        "documentTypes": [
          {
            "id": "04b42e5bf858a66de2229227deaa21e3",
            "shortName": "Decisions",
            "name": "Decisions"
          }
        ],
        "language": "EN",
        "dataSource": 0,
        "referenced": 165,
        "literatureReferenced": 103,
        "score": 24.674826,
        "sourceUrl": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:62018CJ0311"
      }
    ],
    "facets": {
      "DataSources": [
        {
          "shortName": "EU",
          "name": "European Union",
          "value": "0",
          "count": 128,
          "portals": [
            {
              "name": "eur-lex.europa.eu",
              "value": "0|eur-lex.europa.eu",
              "count": 59
            }
          ]
        }
      ],
      "Portals": [
        {
          "shortName": "eur-lex.europa.eu",
          "name": "eur-lex.europa.eu",
          "value": "eur-lex.europa.eu",
          "count": 59
        }
      ],
      "FieldsOfLaw": [
        {
          "shortName": "Public law",
          "name": "Public law",
          "value": "2f6b898befaa9e641cd8ee258cd8f22e",
          "count": 1,
          "tooltip": "Public law",
          "children": []
        }
      ],
      "DocumentTypes": [
        {
          "shortName": "Decisions",
          "name": "Decisions",
          "value": "04b42e5bf858a66de2229227deaa21e3",
          "count": 33,
          "tooltip": "Decisions",
          "children": []
        }
      ],
      "sources": [
        {
          "shortName": "International courts",
          "name": "International courts",
          "value": "f7875ac0576a21c24937d480f6fde4f1",
          "count": 30,
          "tooltip": "International courts",
          "children": []
        }
      ]
    }
  },
  "success": true
}

Filters

GET/v1.1/search/filters/documenttypes

List Document Types

Returns document type IDs structured as a hierarchical tree with nested child categories for filtering search endpoints.

Example Request

curl "https://api.moonlit.ai/v1.1/search/filters/documenttypes" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

{
  "DocumentTypes": [
    {
      "name": "value",
      "id": "value",
      "children": [
        "..."
      ]
    }
  ]
}
GET/v1.1/search/filters/jurisdictions_portals

List Jurisdictions and Portals

Returns jurisdiction names and their portals. Use each portal's `value` field as the canonical `portals` filter input for search endpoints.

Example Request

curl "https://api.moonlit.ai/v1.1/search/filters/jurisdictions_portals" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

[
  {
    "name": "value",
    "count": 0,
    "portals": [
      {
        "name": "value",
        "value": "value",
        "count": 0
      }
    ]
  }
]
GET/v1.1/search/filters/trees

List Fields-of-Law Tree

Returns hierarchical fields-of-law for use in search filters.

Example Request

curl "https://api.moonlit.ai/v1.1/search/filters/trees" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

{
  "FieldsOfLaw": [
    {
      "name": "value",
      "id": "value",
      "children": [
        "..."
      ]
    }
  ]
}
GET/v1.1/search/filters/sources

List Sources

Returns the hierarchical list of sources available for filtering search endpoints. Sources are issuing entities such as Supreme Courts, Courts of Appeal, and Legislative bodies. Each item contains a `value` field — pass that value in the `sources` array of keyword or semantic search requests to filter results by source. Optionally narrow the returned sources by providing `jurisdictions` and/or `portals` as query parameters.

Example Request

curl "https://api.moonlit.ai/v1.1/search/filters/sources" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

{
  "Sources": [
    {
      "name": "value",
      "value": "value",
      "count": 0,
      "children": [
        "..."
      ],
      "parentId": "value"
    }
  ]
}
GET/v1.1/search/semantic_portals

List Semantic Portals

Returns the list of portals currently enabled as semantic-search sources.

Example Request

curl "https://api.moonlit.ai/v1.1/search/semantic_portals" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

[
  {
    "name": "value",
    "value": "value"
  }
]

Documents

GET/v1.1/document/retrieve_document

Retrieve Document

Retrieve full document content and metadata by identifier.

Parameters

ParameterTypeDescription
DocumentIdentifierstringUnique identifier of the document to retrieve.

Example Request

curl "https://api.moonlit.ai/v1.1/document/retrieve_document?DocumentIdentifier=32019L0001" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

{
  "identifier": "32019L0001",
  "language": "EN",
  "date": "2018-12-11",
  "source": "European Parliament",
  "jurisdiction": "European Union",
  "portal": "eur-lex.europa.eu",
  "sourceUrl": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32019L0001",
  "sourcePdf": "https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=32019L0001",
  "sources": [
    {
      "id": "b49c23adeaa6a345aa815e401c6d194b",
      "name": "Legislative bodies"
    },
    {
      "id": "c9aca61be7de06a023b67cc6ab78bf72",
      "parentId": "b49c23adeaa6a345aa815e401c6d194b",
      "name": "European Parliament"
    }
  ],
  "documentTypes": [
    {
      "id": "87a86c141d2c0649a699745ba63e4c6b",
      "parentId": "18fead608f1a4dcb5671b9fc8aeab4d1",
      "name": "European law"
    },
    {
      "id": "18fead608f1a4dcb5671b9fc8aeab4d1",
      "name": "Laws and regulations"
    },
    {
      "id": "f01159d4ed0dc13c024b743d514e1401",
      "parentId": "8dba0d10dfdf2460a34ddf4eeb7b6584",
      "name": "EU directives"
    },
    {
      "id": "8dba0d10dfdf2460a34ddf4eeb7b6584",
      "parentId": "87a86c141d2c0649a699745ba63e4c6b",
      "name": "EU secondary law"
    }
  ],
  "text": "14.1.2019 EN Official Journal of the European Union...",
  "html": "<h1>DIRECTIVE (EU) 2019/1 OF THE EUROPEAN PARLIAMENT...",
  "year": 2019,
  "inForce": true,
  "summary": "This directive establishes common rules for the internal market..."
}
GET/v1.1/document/articles

List Document Articles

Returns the list of articles/elements within a composite document (e.g. a law or regulation). Each article includes its identifier, title, hierarchy level, and the number of documents that reference it. Use the `elementIdentifier` from the response as the `article_reference_id` parameter in reference search to narrow results to a specific article. Set `hierarchy=true` to receive a nested tree structure where child articles are nested under their parent elements based on the `level` field.

Parameters

ParameterTypeDescription
DocumentIdentifierstringUnique identifier of the document to list articles for.

Example Request

curl "https://api.moonlit.ai/v1.1/document/articles?DocumentIdentifier=32016R0679" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY"

Example Response

[
  {
    "elementIdentifier": "value",
    "elementTitle": "value",
    "elementSubTitle": "value",
    "elementHtml": "value",
    "referenceCount": 0,
    "level": 0,
    "globalOrder": 0,
    "children": [
      {
        "elementIdentifier": "value",
        "elementTitle": "value",
        "elementSubTitle": "value",
        "elementHtml": "value",
        "referenceCount": 0,
        "level": 0,
        "globalOrder": 0,
        "children": "..."
      }
    ]
  }
]

Luna AI

POST/v1.1/luna/initialize_chat

Initialize a Luna research chat session

Creates a new research chat session and returns a chat_id for subsequent questions.

Example Request

curl -X POST "https://api.moonlit.ai/v1.1/luna/initialize_chat" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Example Response

{
  "chat_id": "value"
}
POST/v1.1/luna/ask_question

Ask a research question (SSE stream)

Sends a question to an existing Luna research chat session and streams the answer back as Server-Sent Events (SSE).

Parameters

ParameterTypeDescription
chat_idstringChat session ID returned by initialize_chat
inputstringThe research question to ask

Example Request

curl -N -X POST "https://api.moonlit.ai/v1.1/luna/ask_question" \
  -H "Ocp-Apim-Subscription-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "chat_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "input": "What are the key requirements for valid consent under GDPR?",
  "jurisdictions": [
    "European Union",
    "Netherlands"
  ]
}'

Example Response

event: message
data: Based on the relevant case law and legislation...

event: message
data:  the key requirements include...

event: sources
data: {"sources": [{"id": "62018CJ0311", "title": "Schrems II", "relevance": 0.96}]}

event: done
data: [DONE]