Midpage Citations API

Bluebook-style citation lookup and AI-powered citator data returned with retrieved opinions - reporter citations, citation counts, an overall treatment signal (Negative, Caution, Neutral), and per-citing-opinion treatment detail with supporting quotes.

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'