> ## Documentation Index
> Fetch the complete documentation index at: https://docs.medlistiq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract a deduplicated medication list from clinical PDFs

> Accepts one or more clinical PDFs (referral packets, H&Ps, MARs, progress notes, discharge summaries) for a single patient and returns a curated, deduplicated medication list. Each medication carries the document / page / text-snippet evidence it was inferred from across all submitted documents.

Every medication is normalized to RxNorm at the most-specific level the source supports (SCD / SBD / GPCK / BPCK when ingredient + strength + dose form are available; ingredient-level codes otherwise). Ingredients are surfaced with per-ingredient strengths from RxNorm, routes are coded in SNOMED CT + NCI Thesaurus, and combo products / branded packs collapse into one entry per drug.

Limits: up to 15 files per request, 50 MB per file, 150 MB total, 200 pages combined. Larger packets should be split into multiple calls; server-side batching for very large packets is on the roadmap.



## OpenAPI

````yaml https://api.medlistiq.com/openapi.json post /v1/med-lists/from-documents
openapi: 3.1.0
info:
  title: MedListIQ
  description: Infer a deduplicated medication list from FHIR medication resources.
  version: 0.1.0
servers:
  - url: https://api.medlistiq.com
    description: Production
security: []
paths:
  /v1/med-lists/from-documents:
    post:
      summary: Extract a deduplicated medication list from clinical PDFs
      description: >-
        Accepts one or more clinical PDFs (referral packets, H&Ps, MARs,
        progress notes, discharge summaries) for a single patient and returns a
        curated, deduplicated medication list. Each medication carries the
        document / page / text-snippet evidence it was inferred from across all
        submitted documents.


        Every medication is normalized to RxNorm at the most-specific level the
        source supports (SCD / SBD / GPCK / BPCK when ingredient + strength +
        dose form are available; ingredient-level codes otherwise). Ingredients
        are surfaced with per-ingredient strengths from RxNorm, routes are coded
        in SNOMED CT + NCI Thesaurus, and combo products / branded packs
        collapse into one entry per drug.


        Limits: up to 15 files per request, 50 MB per file, 150 MB total, 200
        pages combined. Larger packets should be split into multiple calls;
        server-side batching for very large packets is on the roadmap.
      operationId: from_documents_v1_med_lists_from_documents_post
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: >-
                #/components/schemas/Body_from_documents_v1_med_lists_from_documents_post
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FromDocumentsResponse'
        '401':
          description: Missing or invalid API key.
        '422':
          description: >-
            Validation failure — no files, wrong content type, files too large,
            or total page count exceeds the synchronous limit (200 pages).
        '429':
          description: Rate limit or monthly cap exceeded.
        '503':
          description: >-
            OCR service is not configured or temporarily unavailable. Retry with
            backoff.
      security:
        - BearerAuth: []
components:
  schemas:
    Body_from_documents_v1_med_lists_from_documents_post:
      properties:
        files:
          items:
            type: string
            contentMediaType: application/octet-stream
          type: array
          title: Files
        external_patient_id:
          anyOf:
            - type: string
            - type: 'null'
          title: External Patient Id
      type: object
      required:
        - files
      title: Body_from_documents_v1_med_lists_from_documents_post
    FromDocumentsResponse:
      properties:
        medications:
          items:
            $ref: '#/components/schemas/ExtractedMedication'
          type: array
          title: Medications
          description: >-
            Reconciled medication list. Ordered by the section recency of each
            medication's canonical mention, then alphabetically by drug name.
      type: object
      required:
        - medications
      title: FromDocumentsResponse
      description: |-
        Body shape of ``POST /v1/med-lists/from-documents``.

        Body-only by design — request id, processing time, page counts, and
        ruleset version live in response headers (``x-request-id``,
        ``x-processing-time-ms``, ``x-document-count``, ``x-total-page-count``,
        ``x-output-medication-count``, ``x-ruleset-version``).
    ExtractedMedication:
      properties:
        drug_name:
          type: string
          title: Drug Name
          description: >-
            Human-readable name for the medication. When we resolved a specific
            RxNorm code (SCD / SBD / GPCK / BPCK), this is the catalog's
            canonical name for that code — already including ingredient,
            strength, and dose form (e.g. "penicillin V Potassium 250 MG Oral
            Tablet"). When we could only resolve to an ingredient-level concept,
            this is the lexicon-canonical name ("Metformin"). The structured
            fields below carry the same data in machine-readable form and
            reflect what the source document actually said — which may differ
            from the canonical strength when the patient is on a non-standard
            dose.
          examples:
            - penicillin V Potassium 250 MG Oral Tablet
        rxnorm_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Rxnorm Code
          description: >-
            Most-specific RxNorm rxcui we could resolve for this medication. We
            prefer SCD / SBD / GPCK / BPCK (ingredient + strength + dose form)
            over less-specific term types, and only fall back to
            ingredient-level codes (IN / PIN) when the inputs lacked the fields
            we'd need to pin down a specific drug. Use rxnorm_tty to tell which
            level you got. Null when no rxcui matched at all (rare — usually
            uncommon drugs not in RxNorm).
          examples:
            - '834061'
        rxnorm_tty:
          anyOf:
            - type: string
            - type: 'null'
          title: Rxnorm Tty
          description: >-
            Term type of rxnorm_code. SCD / SBD / GPCK / BPCK indicate a
            fully-specified drug (use confidently for prescribing). SCDC / SBDC
            indicate ingredient + strength but no dose form. IN / PIN / MIN / BN
            indicate ingredient-only — treat as a fallback for class-level
            clinical decision support. Null when rxnorm_code is null.
          examples:
            - SCD
        ingredients:
          items:
            $ref: '#/components/schemas/Ingredient'
          type: array
          title: Ingredients
          description: >-
            Ingredients of this medication, each with its RxNorm code, term
            type, and per-ingredient strength when known. A single-ingredient
            drug has one entry; a multi-ingredient drug (e.g. amlodipine /
            valsartan) has one entry per ingredient. Use the rxnorm_code on each
            as the key for drug-interaction checks and class-level allergy
            matching, where the SCD-level top-level rxnorm_code is usually too
            specific. Empty when we could not resolve any ingredient.
        dose_quantity:
          anyOf:
            - type: string
            - type: 'null'
          title: Dose Quantity
          description: >-
            Numeric portion of the parsed dose, kept as a string so range values
            like '1-2' and decimals like '12.5' survive verbatim. Pair with
            dose_unit. Null when no dose was detected.
          examples:
            - '500'
        dose_unit:
          anyOf:
            - type: string
            - type: 'null'
          title: Dose Unit
          description: >-
            Unit portion of the parsed dose (e.g. 'mg', 'mcg', 'ml', 'tablets').
            Lowercase. Null when no dose was detected.
          examples:
            - mg
        route:
          anyOf:
            - type: string
            - type: 'null'
          title: Route
          description: >-
            Normalized route abbreviation (PO, IV, IM, SC, INH, TOP, VAG, PR,
            TD, OPH, OTIC, NAS). Populated from the source text when one was
            mentioned; otherwise enriched from the resolved RxNorm dose form
            when possible.
          examples:
            - PO
        route_snomed_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Route Snomed Code
          description: >-
            SNOMED CT code for the route, when ``route`` is set and matches a
            code in our route table (covers the ~30 most common administration
            routes — 95%+ of real use). ``http://snomed.info/sct`` is the
            implicit system. ``null`` when ``route`` is null or unrecognized.
          examples:
            - '26643006'
        route_ncit_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Route Ncit Code
          description: >-
            NCI Thesaurus (NCIT) code for the route, paired with
            ``route_snomed_code``. The two coding systems target different
            downstream consumers (FHIR / clinical-decision support tend to
            expect SNOMED; oncology and research datasets tend to expect NCIT).
            ``http://ncithesaurus.nci.nih.gov`` is the implicit system.
          examples:
            - C38288
        dose_form:
          anyOf:
            - type: string
            - type: 'null'
          title: Dose Form
          description: >-
            Dose form phrase (``oral tablet``, ``vaginal system``, ``transdermal
            patch``, …). Lowercase. Populated from the source text when present;
            otherwise enriched from the RxNorm canonical name when we resolved a
            specific RxCUI. ``null`` when we couldn't derive one.
          examples:
            - oral tablet
        frequency:
          anyOf:
            - type: string
            - type: 'null'
          title: Frequency
          description: >-
            Normalized frequency abbreviation (BID, TID, QHS, PRN, Q6H, etc).
            Phrases like 'twice daily' are mapped to BID.
          examples:
            - BID
        sources:
          items:
            $ref: '#/components/schemas/ExtractedMedicationSource'
          type: array
          title: Sources
          description: >-
            Per-mention evidence — one entry per detected mention across all
            input documents.
      type: object
      required:
        - drug_name
        - sources
      title: ExtractedMedication
      description: One reconciled medication, merged across all submitted documents.
    Ingredient:
      properties:
        rxnorm_code:
          type: string
          title: Rxnorm Code
          description: RxNorm rxcui for the ingredient.
          examples:
            - '83367'
        name:
          type: string
          title: Name
          description: Canonical ingredient name from RxNorm.
          examples:
            - atorvastatin
        rxnorm_tty:
          type: string
          title: Rxnorm Tty
          description: >-
            RxNorm term type — typically IN (Ingredient), PIN (Precise
            Ingredient — salt forms), or MIN (Multi-Ingredient).
          examples:
            - IN
        strength_quantity:
          anyOf:
            - type: string
            - type: 'null'
          title: Strength Quantity
          description: >-
            Numeric strength of this ingredient WITHIN the parent medication, as
            published by RxNorm (read from the ingredient's Semantic Clinical
            Drug Component). ``"800"`` for the 800 mg sulfamethoxazole component
            of Bactrim. Pair with ``strength_unit``. Null when the parent drug
            couldn't be resolved to a specific RxCUI or RxNorm doesn't publish a
            strength for this combination.
          examples:
            - '800'
        strength_unit:
          anyOf:
            - type: string
            - type: 'null'
          title: Strength Unit
          description: >-
            Unit for ``strength_quantity`` — e.g. ``"mg"``, ``"mcg"``,
            ``"mg/hr"`` (transdermal patches and vaginal systems). Lowercase.
            Null when ``strength_quantity`` is null.
          examples:
            - mg
      type: object
      required:
        - rxnorm_code
        - name
        - rxnorm_tty
      title: Ingredient
      description: |-
        One ingredient of a medication, with the strength RxNorm publishes
        for it within the parent product.

        Single-ingredient drugs surface one of these on the parent
        medication; multi-ingredient combinations (e.g. amlodipine /
        valsartan) surface one entry per ingredient.
    ExtractedMedicationSource:
      properties:
        document_name:
          type: string
          title: Document Name
          description: Filename of the input PDF this mention came from.
          examples:
            - discharge_summary.pdf
        page:
          type: integer
          minimum: 1
          title: Page
          description: 1-indexed page number within the source PDF.
          examples:
            - 3
        evidence_text:
          type: string
          title: Evidence Text
          description: The raw text line where the mention was matched.
          examples:
            - Metformin 500 mg twice daily
      type: object
      required:
        - document_name
        - page
        - evidence_text
      title: ExtractedMedicationSource
      description: |-
        One evidence span — where in the input PDFs we found this med.

        The reconciler aggregates one entry per detected mention across all
        submitted documents, so a med corroborated by 3 docs has 3 sources.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        MedListIQ API key (format: `ml_...`). Create one at [Dashboard → API
        Keys](https://medlistiq.com/dashboard/keys).

````