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

# Compare reported availability for a bounded product list

> Evaluates up to 25 exact products, identified by either Nektir product IDs or Utah DABS SKUs,
against inventory already stored by Nektir. `product_ids` and `skus` are mutually exclusive and
one is required. The request never
waits for or triggers a Utah DABS refresh. All strategies use the same publication revision,
radius, retrieval-age policy, and purchase-eligibility mode.

`fewest_stores_complete` minimizes store count first. Equal-stop plans minimize the farthest
store's straight-line distance from the supplied coordinates, then total straight-line origin
distance. Distances are not driving routes. A missing solution or empty result does not establish
that stock is unavailable when `meta.coverage.unchecked_pair_count` is positive.




## OpenAPI

````yaml /openapi/v1.yaml get /availability/comparison
openapi: 3.1.0
info:
  title: Independent Utah DABS API
  version: 1.0.0
  summary: Database-backed product, store, and reported-inventory reads
  description: >
    Version 1 pilot contract. All requests read a locally published database
    revision;

    no public request waits for or triggers Utah DABS. Reported quantities are

    observations, not purchase guarantees. This service is independent and is
    not

    affiliated with or endorsed by Utah DABS. The current local seed contains

    historical inventory fixtures; clients must inspect response warnings and

    coverage metadata.
servers:
  - url: http://127.0.0.1:5185/v1
    description: Local development only; set MINTLIFY_API_BASE_URL before publishing
security: []
tags:
  - name: Products
  - name: Search
  - name: Brands
  - name: Product families
  - name: Changes
  - name: Exports
  - name: Stores
  - name: Availability
  - name: Metadata
paths:
  /availability/comparison:
    get:
      tags:
        - Availability
      summary: Compare reported availability for a bounded product list
      description: >
        Evaluates up to 25 exact products, identified by either Nektir product
        IDs or Utah DABS SKUs,

        against inventory already stored by Nektir. `product_ids` and `skus` are
        mutually exclusive and

        one is required. The request never

        waits for or triggers a Utah DABS refresh. All strategies use the same
        publication revision,

        radius, retrieval-age policy, and purchase-eligibility mode.


        `fewest_stores_complete` minimizes store count first. Equal-stop plans
        minimize the farthest

        store's straight-line distance from the supplied coordinates, then total
        straight-line origin

        distance. Distances are not driving routes. A missing solution or empty
        result does not establish

        that stock is unavailable when `meta.coverage.unchecked_pair_count` is
        positive.
      operationId: compareProductAvailability
      parameters:
        - $ref: '#/components/parameters/ComparisonProductIds'
        - $ref: '#/components/parameters/ComparisonSkus'
        - $ref: '#/components/parameters/ComparisonLatitude'
        - $ref: '#/components/parameters/ComparisonLongitude'
        - $ref: '#/components/parameters/RadiusMeters'
        - $ref: '#/components/parameters/ComparisonStrategies'
        - $ref: '#/components/parameters/ComparisonPurchaseEligibility'
        - $ref: '#/components/parameters/InventoryAge'
        - $ref: '#/components/parameters/ComparisonMaxStops'
        - $ref: '#/components/parameters/IfNoneMatch'
        - $ref: '#/components/parameters/IfModifiedSince'
      responses:
        '200':
          description: Comparison plans calculated from one immutable publication revision.
          headers:
            ETag:
              $ref: '#/components/headers/ETag'
            Last-Modified:
              $ref: '#/components/headers/LastModified'
            Cache-Control:
              $ref: '#/components/headers/InventoryCacheControl'
            X-Publication-Revision:
              $ref: '#/components/headers/PublicationRevision'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AvailabilityComparisonResponse'
        '304':
          $ref: '#/components/responses/NotModified'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/Unavailable'
components:
  parameters:
    ComparisonProductIds:
      name: product_ids
      in: query
      style: form
      explode: false
      description: >-
        Comma-separated exact stable product UUIDs, mutually exclusive with
        `skus`. Order is preserved in `requested_products`.
      schema:
        type: array
        minItems: 1
        maxItems: 25
        uniqueItems: true
        items:
          type: string
          format: uuid
    ComparisonSkus:
      name: skus
      in: query
      style: form
      explode: false
      description: >-
        Comma-separated current or unambiguous historical six-digit Utah DABS
        SKUs, mutually exclusive with `product_ids`. Leading zeros and order are
        preserved.
      schema:
        type: array
        minItems: 1
        maxItems: 25
        uniqueItems: true
        items:
          type: string
          pattern: ^\d{6}$
    ComparisonLatitude:
      name: lat
      in: query
      required: true
      description: >-
        Required WGS84 origin latitude used for radius and straight-line
        ranking.
      schema:
        type: number
        format: double
        minimum: -90
        maximum: 90
    ComparisonLongitude:
      name: lng
      in: query
      required: true
      description: >-
        Required WGS84 origin longitude used for radius and straight-line
        ranking.
      schema:
        type: number
        format: double
        minimum: -180
        maximum: 180
    RadiusMeters:
      name: radius_m
      in: query
      description: Radius in meters; valid only with coordinates.
      schema:
        type: integer
        minimum: 1
        maximum: 500000
        default: 50000
    ComparisonStrategies:
      name: strategies
      in: query
      style: form
      explode: false
      description: Comma-separated strategies to return. Omit to calculate all strategies.
      schema:
        type: array
        maxItems: 5
        uniqueItems: true
        items:
          $ref: '#/components/schemas/AvailabilityComparisonStrategyName'
    ComparisonPurchaseEligibility:
      name: purchase_eligibility
      in: query
      description: >-
        `eligible` plans against reported-positive observations classified for
        ordinary consumer purchase. `any` plans against all reported-positive
        observations while preserving eligibility arrays per store.
      schema:
        type: string
        enum:
          - eligible
          - any
        default: eligible
    InventoryAge:
      name: inventory_age
      in: query
      description: Whether inventory predicates require the current retrieval-age policy.
      schema:
        type: string
        enum:
          - within_policy
          - any_age
        default: within_policy
    ComparisonMaxStops:
      name: max_stops
      in: query
      description: Maximum stores considered by complete and partial multi-store plans.
      schema:
        type: integer
        minimum: 1
        maximum: 3
        default: 3
    IfNoneMatch:
      name: If-None-Match
      in: header
      description: Strong entity tag from an earlier response.
      schema:
        type: string
    IfModifiedSince:
      name: If-Modified-Since
      in: header
      description: HTTP-date fallback validator. ETag takes precedence.
      schema:
        type: string
  headers:
    ETag:
      description: >-
        Strong validator for the response representation. A new publication may
        retain the validator when this response is unchanged.
      schema:
        type: string
      example: '"v1-018f2fd0-a3d4-7d20-9c11-9482722f6b26-a91c"'
    LastModified:
      description: >-
        Newest relevant publication time in HTTP-date format; not an upstream
        update time.
      schema:
        type: string
      example: Tue, 15 Sep 2026 16:31:00 GMT
    InventoryCacheControl:
      schema:
        type: string
      example: public, max-age=30, stale-while-revalidate=120
    PublicationRevision:
      description: Immutable API publication revision used for this representation.
      schema:
        type: string
        format: uuid
    RetryAfter:
      description: Seconds until retry or an HTTP-date.
      schema:
        type: string
    RequestId:
      description: >-
        Server-generated identifier for correlating a response with private
        operational logs.
      schema:
        type: string
        format: uuid
  schemas:
    AvailabilityComparisonResponse:
      type: object
      additionalProperties: false
      required:
        - data
        - meta
      properties:
        data:
          $ref: '#/components/schemas/AvailabilityComparisonData'
        meta:
          $ref: '#/components/schemas/AvailabilityComparisonMeta'
    AvailabilityComparisonStrategyName:
      type: string
      enum:
        - best_single_store
        - closest_store_with_any
        - closest_complete_store
        - fewest_stores_complete
        - best_partial_plan
    AvailabilityComparisonData:
      type: object
      additionalProperties: false
      required:
        - requested_products
        - scope
        - strategies
      properties:
        requested_products:
          type: array
          minItems: 1
          maxItems: 25
          items:
            $ref: '#/components/schemas/AvailabilityComparisonProduct'
        scope:
          $ref: '#/components/schemas/AvailabilityComparisonScope'
        strategies:
          type: array
          minItems: 1
          maxItems: 5
          items:
            $ref: '#/components/schemas/AvailabilityComparisonStrategy'
    AvailabilityComparisonMeta:
      type: object
      additionalProperties: false
      required:
        - coverage
        - warnings
      properties:
        coverage:
          $ref: '#/components/schemas/AvailabilityComparisonCoverage'
        warnings:
          type: array
          items:
            $ref: '#/components/schemas/Warning'
    Problem:
      type: object
      additionalProperties: false
      required:
        - type
        - title
        - status
        - detail
        - instance
        - code
        - request_id
      properties:
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
          minimum: 400
          maximum: 599
        detail:
          type: string
        instance:
          type: string
          format: uri-reference
        code:
          type: string
        request_id:
          type: string
          format: uuid
        invalid_params:
          type: array
          items:
            $ref: '#/components/schemas/InvalidParameter'
    AvailabilityComparisonProduct:
      type: object
      additionalProperties: false
      required:
        - id
        - source_ids
        - name
        - brand
        - brand_id
        - package_size
        - price
        - status
      properties:
        id:
          type: string
          format: uuid
        source_ids:
          $ref: '#/components/schemas/SourceProductIds'
        name:
          type: string
          description: >-
            Consumer display title without the resolved brand or structured
            package dimensions.
        brand:
          type:
            - string
            - 'null'
        brand_id:
          type:
            - string
            - 'null'
          format: uuid
        package_size:
          $ref: '#/components/schemas/PackageSize'
        price:
          oneOf:
            - $ref: '#/components/schemas/MoneyObservation'
            - type: 'null'
        status:
          $ref: '#/components/schemas/ProductStatus'
    AvailabilityComparisonScope:
      type: object
      additionalProperties: false
      required:
        - origin
        - radius_m
        - store_count
        - inventory_age
        - purchase_eligibility
        - max_stops
      properties:
        origin:
          $ref: '#/components/schemas/GeoPoint'
        radius_m:
          type: integer
          minimum: 1
          maximum: 500000
        store_count:
          type: integer
          minimum: 0
        inventory_age:
          type: string
          enum:
            - within_policy
            - any_age
        purchase_eligibility:
          type: string
          enum:
            - eligible
            - any
        max_stops:
          type: integer
          minimum: 1
          maximum: 3
    AvailabilityComparisonStrategy:
      type: object
      additionalProperties: false
      required:
        - strategy
        - result_state
        - completeness_required
        - no_solution_reason
        - plan
      properties:
        strategy:
          $ref: '#/components/schemas/AvailabilityComparisonStrategyName'
        result_state:
          type: string
          enum:
            - complete
            - partial
            - no_solution
        completeness_required:
          type: boolean
        no_solution_reason:
          type:
            - string
            - 'null'
          enum:
            - NO_REPORTED_MATCH
            - NO_SINGLE_STORE_COVERS_ALL_PRODUCTS
            - NO_COMPLETE_PLAN_IN_SCOPE
            - COMPLETE_PLAN_EXCEEDS_MAX_STOPS
            - null
        plan:
          oneOf:
            - $ref: '#/components/schemas/AvailabilityComparisonPlan'
            - type: 'null'
    AvailabilityComparisonCoverage:
      type: object
      additionalProperties: false
      required:
        - selected_coverage_mode
        - covered_product_ids
        - uncovered_product_ids
        - uncertain_product_ids
        - restricted_product_ids
        - reported_positive_product_ids
        - purchase_eligible_product_ids
        - requested_product_count
        - store_count
        - expected_pair_count
        - observed_pair_count
        - unchecked_pair_count
        - retrieved_at_min
        - retrieved_at_max
        - upstream_age_known
      properties:
        selected_coverage_mode:
          type: string
          enum:
            - purchase_eligible_reported_positive
            - reported_positive
        covered_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        uncovered_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        uncertain_product_ids:
          type: array
          uniqueItems: true
          description: >-
            Uncovered products with at least one unchecked product-store pair in
            the requested scope.
          items:
            type: string
            format: uuid
        restricted_product_ids:
          type: array
          uniqueItems: true
          description: >-
            Products reported positive as restricted in scope and never
            classified purchase-eligible there.
          items:
            type: string
            format: uuid
        reported_positive_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        purchase_eligible_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        requested_product_count:
          type: integer
          minimum: 1
          maximum: 25
        store_count:
          type: integer
          minimum: 0
        expected_pair_count:
          type: integer
          minimum: 0
        observed_pair_count:
          type: integer
          minimum: 0
        unchecked_pair_count:
          type: integer
          minimum: 0
        retrieved_at_min:
          type:
            - string
            - 'null'
          format: date-time
        retrieved_at_max:
          type:
            - string
            - 'null'
          format: date-time
        upstream_age_known:
          type: boolean
          const: false
    Warning:
      type: object
      additionalProperties: false
      description: >-
        Machine-readable data qualification. Current codes include FIXTURE_DATA,
        INVENTORY_COVERAGE_PARTIAL, SOURCE_REFRESH_DELAYED,
        UPSTREAM_PRODUCT_UNAVAILABLE, SOURCE_SCHEMA_QUARANTINED, and
        CATALOG_BATCH_OLD.
      required:
        - code
      properties:
        code:
          type: string
          examples:
            - INVENTORY_COVERAGE_PARTIAL
    InvalidParameter:
      type: object
      additionalProperties: false
      required:
        - name
        - reason
      properties:
        name:
          type: string
        reason:
          type: string
    SourceProductIds:
      type: object
      additionalProperties: false
      required:
        - utah_dabs_sku
      properties:
        utah_dabs_sku:
          $ref: '#/components/schemas/DabsSku'
    PackageSize:
      type: object
      additionalProperties: false
      description: >-
        Parsed package dimensions. `milliliters` preserves the legacy normalized
        DABS size value and can describe either a container or a complete
        package; new integrations should use the explicit unit and total fields
        together with `interpretation`. Null means the dimension was not
        established.
      required:
        - milliliters
        - container_count
        - unit_milliliters
        - total_milliliters
        - display
        - interpretation
        - basis
        - normalization_state
      properties:
        milliliters:
          type:
            - integer
            - 'null'
          minimum: 1
          deprecated: true
          description: >-
            Legacy normalized source value with historically ambiguous multipack
            semantics.
        container_count:
          type:
            - integer
            - 'null'
          minimum: 1
        unit_milliliters:
          type:
            - integer
            - 'null'
          minimum: 1
          description: Volume of one container when established.
        total_milliliters:
          type:
            - integer
            - 'null'
          minimum: 1
          description: Calculated total package volume when established.
        display:
          type:
            - string
            - 'null'
          examples:
            - 8 × 355 mL
        interpretation:
          type: string
          enum:
            - single_container
            - multi_container
            - ambiguous
            - missing
        basis:
          type: string
          enum:
            - normalized_source_size
            - explicit_source_name_and_pack_count
            - corroborated_source_name_and_total
            - pack_count_with_ambiguous_source_size
            - none
        normalization_state:
          type: string
          enum:
            - normalized
            - unconfirmed
            - missing
    MoneyObservation:
      type: object
      additionalProperties: false
      required:
        - amount_minor
        - currency
        - display
        - source
        - times
      properties:
        amount_minor:
          type: integer
          format: int64
          minimum: 0
        currency:
          type: string
          const: USD
        display:
          type: string
          examples:
            - $19.99
        source:
          type: string
          enum:
            - utah_dabs_workbook
            - utah_dabs_locator
        times:
          $ref: '#/components/schemas/ObservationTimes'
    ProductStatus:
      type: object
      additionalProperties: false
      required:
        - code
        - label
        - lifecycle
        - source_raw
      properties:
        code:
          type: string
          examples:
            - '1'
        label:
          type: string
          examples:
            - General distribution
        lifecycle:
          type: string
          enum:
            - active
            - discontinued
            - restricted
            - unavailable
            - unknown
        source_raw:
          type: string
    GeoPoint:
      type: object
      additionalProperties: false
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: number
          format: double
          minimum: -90
          maximum: 90
        longitude:
          type: number
          format: double
          minimum: -180
          maximum: 180
    AvailabilityComparisonPlan:
      type: object
      additionalProperties: false
      required:
        - stop_count
        - farthest_store_distance_m
        - total_origin_distance_m
        - distance_metric
        - covered_product_count
        - requested_product_count
        - covered_product_ids
        - uncovered_product_ids
        - stores
      properties:
        stop_count:
          type: integer
          minimum: 1
        farthest_store_distance_m:
          type: integer
          minimum: 0
        total_origin_distance_m:
          type: integer
          minimum: 0
        distance_metric:
          type: string
          const: straight_line_from_supplied_coordinates
        covered_product_count:
          type: integer
          minimum: 1
        requested_product_count:
          type: integer
          minimum: 1
          maximum: 25
        covered_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        uncovered_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        stores:
          type: array
          minItems: 1
          maxItems: 3
          items:
            $ref: '#/components/schemas/AvailabilityComparisonStore'
    DabsSku:
      type: string
      pattern: ^[0-9]{6}$
      examples:
        - '347210'
        - '004190'
    ObservationTimes:
      type: object
      additionalProperties: false
      required:
        - source_updated_at
        - retrieved_at
        - published_at
      properties:
        source_updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: Null when the source supplies no update timestamp.
        retrieved_at:
          type: string
          format: date-time
        published_at:
          type: string
          format: date-time
    AvailabilityComparisonStore:
      type: object
      additionalProperties: false
      required:
        - store
        - assigned_product_ids
        - covered_product_ids
        - reported_product_ids
        - eligible_product_ids
        - covered_product_count
        - selected_coverage_mode
      properties:
        store:
          $ref: '#/components/schemas/StoreSummary'
        assigned_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        covered_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        reported_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        eligible_product_ids:
          type: array
          uniqueItems: true
          items:
            type: string
            format: uuid
        covered_product_count:
          type: integer
          minimum: 0
        selected_coverage_mode:
          type: string
          enum:
            - purchase_eligible_reported_positive
            - reported_positive
    StoreSummary:
      type: object
      additionalProperties: false
      required:
        - id
        - source_ids
        - name
        - address
        - phone
        - contact_links
        - location
        - distance_m
        - access_type
        - operational_status
        - services
        - regular_hours_available
        - directory_presence
        - details_times
      properties:
        id:
          type: string
          format: uuid
        source_ids:
          $ref: '#/components/schemas/StoreSourceIds'
        name:
          type: string
        address:
          $ref: '#/components/schemas/PostalAddress'
        phone:
          type:
            - string
            - 'null'
          description: E.164 when normalization is verified.
        contact_links:
          $ref: '#/components/schemas/ContactLinks'
        location:
          oneOf:
            - $ref: '#/components/schemas/GeoPoint'
            - type: 'null'
        distance_m:
          type:
            - integer
            - 'null'
          minimum: 0
        access_type:
          $ref: '#/components/schemas/StoreAccessType'
        operational_status:
          $ref: '#/components/schemas/StoreOperationalStatus'
        services:
          type: array
          uniqueItems: true
          items:
            type: string
            enum:
              - refrigerated_beer
              - wine_store
              - high_end_product_room
              - curbside_pickup
              - accessible_entrance
              - parking
        regular_hours_available:
          type: boolean
        directory_presence:
          oneOf:
            - $ref: '#/components/schemas/SourcePresenceSummary'
            - type: 'null'
        details_times:
          $ref: '#/components/schemas/ObservationTimes'
    StoreSourceIds:
      type: object
      additionalProperties: false
      required:
        - inventory_store_code
        - directory_id
      properties:
        inventory_store_code:
          oneOf:
            - $ref: '#/components/schemas/StoreInventoryCode'
            - type: 'null'
        directory_id:
          type:
            - string
            - 'null'
    PostalAddress:
      type: object
      additionalProperties: false
      required:
        - line1
        - line2
        - city
        - region
        - postal_code
        - country
      properties:
        line1:
          type: string
        line2:
          type:
            - string
            - 'null'
        city:
          type: string
        region:
          type: string
          examples:
            - UT
        postal_code:
          type: string
        country:
          type: string
          const: US
    ContactLinks:
      type: object
      additionalProperties: false
      required:
        - telephone_uri
        - geo_uri
      properties:
        telephone_uri:
          type:
            - string
            - 'null'
          description: Neutral `tel:` URI, present only when the phone was normalized.
        geo_uri:
          type:
            - string
            - 'null'
          description: Neutral RFC 5870 `geo:` URI derived from published coordinates.
    StoreAccessType:
      type: string
      enum:
        - consumer_state_store
        - licensee_only
        - package_agency
        - unknown
    StoreOperationalStatus:
      type: object
      additionalProperties: false
      required:
        - state
        - note
        - source
      properties:
        state:
          type: string
          enum:
            - open
            - temporarily_closed
            - permanently_closed
            - unknown
        note:
          type:
            - string
            - 'null'
        source:
          type: string
          enum:
            - reviewed_editorial
            - unknown
    SourcePresenceSummary:
      type: object
      additionalProperties: false
      description: Compact presence state for collection rows.
      required:
        - state
        - last_seen_at
      properties:
        state:
          type: string
          enum:
            - present
            - suspect_missing
            - retirement_review_required
            - reviewed_retired
        last_seen_at:
          type:
            - string
            - 'null'
          format: date-time
    StoreInventoryCode:
      type: string
      pattern: ^[0-9]{4}$
      examples:
        - '0002'
  responses:
    NotModified:
      description: Representation has not changed for the supplied validator.
      headers:
        ETag:
          $ref: '#/components/headers/ETag'
        Cache-Control:
          description: Cache policy for the validated representation.
          schema:
            type: string
        X-Publication-Revision:
          $ref: '#/components/headers/PublicationRevision'
    BadRequest:
      description: Invalid parameters, incompatible scope, or cursor/query mismatch.
      headers:
        Cache-Control:
          schema:
            type: string
          example: no-store
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    NotFound:
      description: Published resource or source mapping not found.
      headers:
        Cache-Control:
          schema:
            type: string
          example: no-store
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    RateLimited:
      description: Public read-rate limit exceeded.
      headers:
        Cache-Control:
          schema:
            type: string
          example: no-store
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    InternalError:
      description: >-
        An unexpected server failure. Details are withheld; report the response
        request identifier.
      headers:
        Cache-Control:
          schema:
            type: string
          example: no-store
        X-Request-ID:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    Unavailable:
      description: No safe published database revision is currently readable.
      headers:
        Cache-Control:
          schema:
            type: string
          example: no-store
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'

````