Midpage Document Retrieval API

Retrieve full opinion data by opinion ID, reporter citation, or docket number, with bulk reads of up to 100 items per request. Optionally include full HTML opinion content and detailed citator treatments via the POST /opinions/get endpoint.

OpenAPI Specification

midpage-openapi.yml Raw ↑
openapi: 3.0.1
info:
  title: Midpage Legal Database API
  description: >-
    REST API for Midpage's US legal database ("Caselaw Building Blocks"). Search
    court opinions with semantic (vector), keyword (full-text), or hybrid search;
    retrieve full opinion data by ID, citation, or docket number with citator
    treatments; and read the authenticated user's identity and subscription
    status. Authenticate with a bearer token (API key) in the Authorization header.
  termsOfService: https://www.midpage.ai/
  contact:
    name: Midpage
    url: https://www.midpage.ai/
  version: '1.0'
servers:
  - url: https://app.midpage.ai/api/v1
    description: Production server
security:
  - apiKey: []
paths:
  /search:
    post:
      operationId: searchOpinions
      tags:
        - Search
      summary: Search opinions
      description: >-
        Search for opinions using semantic (vector), keyword (full-text), or
        hybrid search.

        Search modes: `semantic` (vector similarity using AI embeddings),
        `keyword` (Elasticsearch full-text with Lexis/Westlaw-style boolean
        operators), and `hybrid` (semantic + keyword combined with reciprocal
        rank fusion and deduplication).

        Boolean operators (keyword mode only, must be UPPERCASE): AND, OR, NOT,
        "..." (exact phrase), * and ? (wildcards), W/n (proximity within n
        words), and () for grouping.

        Pagination uses `page` (1-indexed) and `page_size` (max 100). Semantic
        search supports limited deep pagination (~500 unique results); keyword
        and hybrid support deep pagination via Elasticsearch.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: query is required and must be a string
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Unauthorized
                  message:
                    type: string
                    example: Invalid API key
  /opinions/get:
    post:
      operationId: getOpinions
      tags:
        - Opinions
      summary: Get opinions
      description: >-
        Retrieve full opinion data by ID, citation, or docket number. Supports
        bulk reads of up to 100 items per request. Provide exactly one of
        `opinion_ids`, `citations`, or `docket` (not multiple).

        Lookup methods: `opinion_ids` (direct lookup, up to 100), `citations`
        (reporter citation, case-insensitive, up to 100), and `docket` (docket
        number + court; single lookup, may return multiple opinions).

        When using `citations` or `docket`, a lookup may match multiple opinions
        (e.g., majority and dissent from the same case). The response includes
        `citation_matches` or `docket_matches` arrays showing which lookups
        matched which opinion IDs.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                opinion_ids:
                  type: array
                  items:
                    type: string
                  description: Array of opinion IDs to retrieve
                  example:
                    - '8623588'
                    - '1865773'
                citations:
                  type: array
                  items:
                    type: string
                  description: Array of citation strings to look up (case-insensitive)
                  example:
                    - 556 U.S. 662
                    - 550 U.S. 544
                docket:
                  $ref: '#/components/schemas/DocketLookup'
                include_content:
                  type: boolean
                  default: false
                  description: Include full HTML content
                include_detailed_treatments:
                  type: boolean
                  default: false
                  description: Include citator treatments
      responses:
        '200':
          description: Opinion data
          content:
            application/json:
              schema:
                type: object
                properties:
                  opinions:
                    type: array
                    items:
                      $ref: '#/components/schemas/OpinionFull'
                  citation_matches:
                    type: array
                    items:
                      $ref: '#/components/schemas/CitationMatch'
                    description: >-
                      Only present when looking up by `citations`. Shows which
                      citations matched which opinion IDs.
                  docket_matches:
                    type: array
                    items:
                      $ref: '#/components/schemas/DocketMatch'
                    description: >-
                      Only present when looking up by `docket`. Shows which
                      opinions matched.
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: >-
                      Must provide one of: opinion_ids, citations (as arrays), or
                      docket (object with docket_number)
  /me:
    get:
      operationId: getCurrentUser
      tags:
        - User
      summary: Get current user
      description: >-
        Retrieve the authenticated user's Midpage identity and current
        subscription status. Authenticate with a bearer token in the
        Authorization header. Supported bearer tokens: OAuth access token or API
        key. Common subscription statuses: `active`, `trialing`, `past_due`,
        `canceled`. If no subscription status is available, `subscriptionStatus`
        may be `null`.
      responses:
        '200':
          description: Current user profile
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CurrentUserResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Unauthorized
components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        API key authentication. Get your API key from the Midpage Developer
        Portal at https://app.midpage.ai/developers
  schemas:
    CurrentUserResponse:
      type: object
      required:
        - userId
        - subscriptionStatus
      properties:
        userId:
          type: string
          description: Midpage user identifier
          example: user_123
        subscriptionStatus:
          type: string
          nullable: true
          description: >-
            Current subscription status. Common values include `active`,
            `trialing`, `past_due`, and `canceled`. May be `null` if no
            subscription status is available.
          example: active
    SearchRequest:
      type: object
      required:
        - query
      properties:
        query:
          type: string
          description: Search query text
          example: breach of fiduciary duty
        mode:
          type: string
          enum:
            - semantic
            - keyword
            - hybrid
          default: semantic
          description: >-
            Search mode: `semantic` (vector similarity, default), `keyword`
            (full-text), or `hybrid` (combined semantic and keyword results using
            reciprocal rank fusion).
        page:
          type: integer
          minimum: 1
          default: 1
          description: Page number (1-indexed)
        page_size:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
          description: Results per page (max 100)
        filters:
          $ref: '#/components/schemas/SearchFilters'
        include_facets:
          type: boolean
          default: false
          description: >-
            Include facet breakdowns in the response showing result counts by
            court, jurisdiction, state, and year. Facets are only available in
            `keyword` and `hybrid` modes (not `semantic`). In `hybrid` mode,
            facet counts reflect keyword search results only.
    SearchFilters:
      type: object
      description: Optional filters to narrow search results
      properties:
        court_ids:
          type: array
          items:
            type: string
          description: Filter by court IDs (e.g., "ca9", "scotus", "nysd")
          example:
            - ca9
            - ca2
        jurisdictions:
          type: array
          items:
            type: string
            enum:
              - Federal Appellate
              - Federal District
              - State Supreme
              - State Appellate
              - State Trial
              - Federal Bankruptcy
              - Federal Bankruptcy Panel
              - Federal Special
              - Military Appellate
              - State Attorney General
              - State Special
              - U.S. Territory
              - Committee
              - International
              - Tribal
              - Tribal Appellate
              - Tribal Supreme
              - Tribal Trial
          description: >-
            Filter by jurisdiction type using canonical values from Midpage court
            metadata.
          example:
            - Federal Appellate
            - State Supreme
        states:
          type: array
          items:
            type: string
          description: >-
            Filter by state using full canonical names from Midpage court
            metadata.
          example:
            - California
            - New York
        publish_status:
          type: string
          description: >-
            Filter by publication status. Use `unknown` to include opinions where
            publication metadata is missing or uncertain.
          enum:
            - published
            - unpublished
            - unknown
            - in_chambers
            - separate
            - errata
            - relating_to
          example: published
        date_filed:
          type: object
          description: Filter by filing date range
          properties:
            start:
              type: string
              format: date
              description: Start date (YYYY-MM-DD)
              example: '2020-01-01'
            end:
              type: string
              format: date
              description: End date (YYYY-MM-DD)
              example: '2024-12-31'
    SearchResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/SearchResultItem'
        pagination:
          $ref: '#/components/schemas/PaginationMeta'
        metadata:
          type: object
          properties:
            mode:
              type: string
              enum:
                - semantic
                - keyword
                - hybrid
              description: Search mode used
            query:
              type: string
              description: Original query
            processing_time_ms:
              type: integer
              description: Server processing time in milliseconds
            boolean_query:
              type: object
              description: Present in keyword mode when boolean operators are detected
              properties:
                detected:
                  type: boolean
                  description: Whether boolean operators were detected
                operators:
                  type: array
                  items:
                    type: string
                  description: List of detected operators (e.g., ["AND", "OR", "W/5"])
        facets:
          $ref: '#/components/schemas/SearchFacets'
    SearchFacets:
      type: object
      description: >-
        Facet breakdowns showing result counts by various dimensions. Only
        present when `include_facets: true` in request and mode is `keyword` or
        `hybrid`. Counts are computed across the full result set (after filters),
        not just the current page.
      properties:
        court_abbreviation:
          type: array
          items:
            $ref: '#/components/schemas/FacetBucket'
          description: Breakdown by court abbreviation (e.g., "9th Cir.", "S.D.N.Y.")
        jurisdiction:
          type: array
          items:
            $ref: '#/components/schemas/FacetBucket'
          description: Breakdown by jurisdiction type
        state:
          type: array
          items:
            $ref: '#/components/schemas/FacetBucket'
          description: Breakdown by state name
        year_filed:
          type: array
          items:
            $ref: '#/components/schemas/FacetBucket'
          description: Breakdown by filing year
        note:
          type: string
          description: Explanatory note about facet limitations.
          example: >-
            Facet counts reflect keyword search results only; semantic (Pinecone)
            results are not included in these counts.
    FacetBucket:
      type: object
      description: A single bucket in a facet breakdown
      properties:
        key:
          type: string
          description: The value (e.g., "9th Cir.", "Federal Appellate", "2024")
        count:
          type: integer
          description: Number of documents matching this value
    SearchResultItem:
      type: object
      properties:
        opinion_id:
          type: string
          description: Opinion identifier
        score:
          type: number
          description: >-
            Relevance score. Scale varies by mode: semantic 0-1 (cosine
            similarity), keyword 0-100+ (BM25 score).
        case_name:
          type: string
          description: Case name/caption
        court_id:
          type: string
          description: Court identifier
        court_name:
          type: string
          description: Full court name
        court_abbreviation:
          type: string
          description: Court citation abbreviation
        jurisdiction:
          type: string
          description: Jurisdiction type
        state:
          type: string
          nullable: true
          description: State name (null for federal courts)
        publish_status:
          type: string
          nullable: true
          description: Publication status, when available
          enum:
            - published
            - unpublished
            - unknown
            - in_chambers
            - separate
            - errata
            - relating_to
        date_filed:
          type: string
          format: date
          description: Filing date (YYYY-MM-DD)
        docket_number:
          type: string
          nullable: true
          description: Court docket number, when available
        snippet:
          type: string
          description: Relevant text excerpt from the opinion
        source:
          type: string
          enum:
            - semantic
            - keyword
          description: >-
            Source of this result. Always present in API responses: semantic mode
            "semantic", keyword mode "keyword", hybrid mode varies per item.
    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
          description: Current page number
        page_size:
          type: integer
          description: Results per page
        total_results:
          type: integer
          description: Total matching results (capped at 10,000 for keyword/hybrid)
        total_pages:
          type: integer
          description: Total pages available
        has_next:
          type: boolean
          description: Whether more pages exist
        has_prev:
          type: boolean
          description: Whether previous pages exist
    OpinionFull:
      type: object
      properties:
        id:
          type: string
          description: Opinion identifier
        case_name:
          type: string
          description: Case name/caption
        court_id:
          type: string
          description: Court identifier
        court_abbreviation:
          type: string
          description: Citation abbreviation
        docket_number:
          type: string
          description: Court docket number
        date_filed:
          type: string
          format: date
          description: Filing date
        state:
          type: string
          nullable: true
          description: State name (null for federal courts)
        publish_status:
          type: string
          enum:
            - published
            - unpublished
            - unknown
            - in_chambers
            - separate
            - errata
            - relating_to
          description: >-
            Publication status for the opinion. Missing or uncertain metadata is
            returned as unknown.
        judge_name:
          type: string
          description: Authoring judge
        citations:
          type: array
          items:
            $ref: '#/components/schemas/Citation'
        citation_count:
          type: integer
          description: Number of times this opinion is cited by other opinions
        overall_treatment:
          type: string
          nullable: true
          enum:
            - Negative
            - Caution
            - Neutral
          description: >-
            Most negative treatment category from all citing opinions. Always
            returned. Priority: Negative > Caution > Neutral > null (no treatment
            data).
        treatments:
          type: array
          items:
            $ref: '#/components/schemas/Treatment'
          description: >-
            Citator treatments (only included if
            include_detailed_treatments=true)
        html_content:
          type: string
          description: Full opinion text in HTML (only included if include_content=true)
    Citation:
      type: object
      properties:
        cited_as:
          type: string
          description: Full citation string
        volume:
          type: string
          description: Reporter volume
        reporter:
          type: string
          description: Reporter abbreviation
        page:
          type: string
          description: Starting page
    Treatment:
      type: object
      properties:
        citing_id:
          type: string
          description: ID of opinion citing this one
        treatment_category:
          type: string
          description: Treatment type
        treatment_description:
          type: string
          description: Detailed treatment
        is_authoritative:
          type: boolean
          description: Whether authoritative
        supporting_quote:
          type: string
          description: Quote supporting the treatment
    CitationMatch:
      type: object
      description: Maps a requested citation to the opinion(s) it matched
      properties:
        citation:
          type: string
          description: The citation string from the request
          example: 556 U.S. 662
        opinion_id:
          type: string
          description: The matched opinion ID
          example: '145875'
    DocketLookup:
      type: object
      description: >-
        Lookup by docket number and court. Requires docket_number and either
        court_id or court_abbreviation.
      required:
        - docket_number
      properties:
        docket_number:
          type: string
          description: The docket number (e.g., "19-1392", "1:23-cv-01234")
          example: 19-1392
        court_id:
          type: string
          description: Court identifier (e.g., "scotus", "ca9", "nysd")
          example: scotus
        court_abbreviation:
          type: string
          description: Court citation abbreviation (e.g., "SCOTUS", "9th Cir.", "S.D.N.Y.")
          example: SCOTUS
    DocketMatch:
      type: object
      description: Maps a docket lookup to the opinion(s) it matched
      properties:
        docket_number:
          type: string
          description: The docket number that matched
          example: 19-1392
        court_id:
          type: string
          description: Court identifier
          example: scotus
        court_abbreviation:
          type: string
          description: Court citation abbreviation
          example: SCOTUS
        opinion_id:
          type: string
          description: The matched opinion ID
          example: '145875'