{
  "openapi": "3.1.0",
  "info": {
    "title": "Loupe: free citation lookup",
    "version": "1.0.0",
    "summary": "Check a US legal citation, find a case by name, and see what Loupe holds. Free, no account, no key.",
    "description": "Loupe checks legal citations against the sources that settle them. These three read-only endpoints need no account. Every answer says what was checked and what was not: 'not_found' and 'unverified' mean Loupe could not find or settle something, which is not proof that it does not exist; 'suspect' is said only when a citation cannot exist as written. Five hundred questions a day from one network. Not legal advice. Add format=md, or send Accept: text/markdown, for Markdown.",
    "contact": {"email": "hello@loupe.legal", "url": "https://loupe.legal/data#agents"},
    "termsOfService": "https://loupe.legal/terms"
  },
  "servers": [{"url": "https://loupe.legal"}],
  "externalDocs": {"description": "What Loupe holds, and how to ask", "url": "https://loupe.legal/data"},
  "paths": {
    "/api/cite": {
      "get": {
        "operationId": "checkCitation",
        "summary": "Check a citation",
        "description": "Whether a US legal citation exists in the sources Loupe checks, which case it names, and whether a pin cite falls inside the opinion. Give it as written, with the case name and year if you have them: the commonest error is a real citation attached to the wrong case.",
        "parameters": [
          {"name": "c", "in": "query", "required": true, "description": "The citation, or a sentence holding up to five. At most 300 characters.", "schema": {"type": "string", "maxLength": 300}, "example": "Ashcroft v. Iqbal, 556 U.S. 662, 678 (2009)"},
          {"$ref": "#/components/parameters/format"}
        ],
        "responses": {
          "200": {"description": "What the check found.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CiteAnswer"}}, "text/markdown": {"schema": {"type": "string"}}}},
          "429": {"$ref": "#/components/responses/TooMany"},
          "503": {"$ref": "#/components/responses/NotChecked"}
        }
      }
    },
    "/api/search": {
      "get": {
        "operationId": "searchCases",
        "summary": "Find a case",
        "description": "The cases in Loupe's index whose names match the words given, or the case a citation names. A case missing from the results may still exist.",
        "parameters": [
          {"name": "q", "in": "query", "required": true, "description": "The parties' names, or a citation such as 556 U.S. 662. At most 120 characters and eight words.", "schema": {"type": "string", "maxLength": 120}, "example": "Miranda v. Arizona"},
          {"name": "year", "in": "query", "required": false, "description": "The year of decision, if known; a year in q is read the same way.", "schema": {"type": "string", "pattern": "^\\d{4}$"}},
          {"$ref": "#/components/parameters/format"}
        ],
        "responses": {
          "200": {"description": "The cases found, and a note on what the search covers.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SearchAnswer"}}, "text/markdown": {"schema": {"type": "string"}}}},
          "429": {"$ref": "#/components/responses/TooMany"},
          "503": {"$ref": "#/components/responses/NotChecked"}
        }
      }
    },
    "/api/coverage": {
      "get": {
        "operationId": "coverage",
        "summary": "What Loupe holds",
        "description": "The citations in Loupe's index, how many opinions it knows the pages of, the newest decision, and what the daily crawler has collected from the courts' own sites. Counted live.",
        "parameters": [{"$ref": "#/components/parameters/format"}],
        "responses": {"200": {"description": "The figures.", "content": {"application/json": {"schema": {"type": "object"}}, "text/markdown": {"schema": {"type": "string"}}}}}
      }
    }
  },
  "components": {
    "parameters": {
      "format": {"name": "format", "in": "query", "required": false, "description": "md for Markdown instead of JSON.", "schema": {"type": "string", "enum": ["md"]}}
    },
    "responses": {
      "TooMany": {"description": "Today's free questions from this network are used. They come back at midnight UTC."},
      "NotChecked": {"description": "Loupe could not read its index or run the check just now. Nothing was checked; this is not a finding. Try again shortly."}
    },
    "schemas": {
      "CiteAnswer": {
        "type": "object",
        "properties": {
          "asked": {"type": "string"},
          "citations": {"type": "array", "items": {"$ref": "#/components/schemas/Checked"}},
          "not_checked": {"type": "object", "additionalProperties": {"type": "string"}, "description": "Checks that did not run, and why."},
          "sources": {"type": "array", "items": {"type": "string"}},
          "caveat": {"type": "string"}
        }
      },
      "Checked": {
        "type": "object",
        "properties": {
          "citation": {"type": "string"},
          "kind": {"type": "string", "description": "case, statute, regulation, court_rule, constitution and the like."},
          "verdict": {"type": "string", "enum": ["verified", "mismatch", "not_found", "suspect", "unverifiable", "unverified"]},
          "in_words": {"type": "string"},
          "case": {"type": ["string", "null"]},
          "court": {"type": ["string", "null"]},
          "decided": {"type": ["string", "null"]},
          "pin": {"type": ["string", "null"]},
          "findings": {"type": "array", "items": {"type": "object", "properties": {"confidence": {"type": "string", "enum": ["certain", "probable", "check", "unverifiable"]}, "problem": {"type": "string"}, "do": {"type": ["string", "null"]}}}},
          "read_it": {"type": "array", "items": {"type": "object", "properties": {"label": {"type": "string"}, "url": {"type": "string", "format": "uri"}}}}
        }
      },
      "SearchAnswer": {
        "type": "object",
        "properties": {
          "query": {"type": "string"},
          "results": {"type": "array", "items": {"type": "object", "properties": {
            "name": {"type": ["string", "null"]}, "decided": {"type": ["string", "null"]},
            "citations": {"type": "array", "items": {"type": "string"}},
            "pages": {"type": ["object", "null"], "properties": {"first": {"type": "integer"}, "last": {"type": "integer"}}},
            "printed_page": {"type": ["boolean", "null"]},
            "read_it": {"type": "array", "items": {"type": "object"}}}}},
          "pin": {"type": "object", "properties": {"page": {"type": "integer"}, "inside": {"type": "boolean"}}},
          "note": {"type": "string"}
        }
      }
    }
  }
}
