{
  "openapi": "3.1.0",
  "info": {
    "title": "State Law Check API",
    "version": "1.26",
    "description": "Whether a knife or self-defense product may ship to a US address, with the exact federal and state law behind each answer. Information, not legal advice; accuracy isn't guaranteed. Draft rules (written from the official law text, not yet reviewed by a lawyer) apply by default since 2026-11-02, and every rule and result says its `basis` (\"draft\" or \"reviewed\"); send `includeDrafts: false` for reviewed rules only. Report a wrong rule with POST /v1/feedback: the change applies to your own keys at once."
  },
  "servers": [
    {
      "url": "https://statelawcheck.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/v1/rules": {
      "get": {
        "summary": "Rules and laws for an address, with an optional product verdict",
        "description": "On the free plan each rule's `when` carries only carriersAny/interstateOnly and the response has `conditions: \"summary\"`; paid plans get full conditions. /v1/check and /v1/matrix verdicts are complete on every plan.",
        "parameters": [
          {
            "name": "zip",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^\\d{5}$"
            },
            "description": "Destination ZIP. More precise than state: city rules match on ZIP."
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Two-letter state. Required if zip is omitted or unknown."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "enum": [
                "folding_knife",
                "fixed_blade",
                "balisong",
                "pepper_spray",
                "stun_gun",
                "other"
              ]
            }
          },
          {
            "name": "mechanism",
            "in": "query",
            "schema": {
              "enum": [
                "manual",
                "assisted",
                "automatic",
                "otf",
                "gravity",
                "fixed",
                "none"
              ]
            }
          },
          {
            "name": "bladeLengthIn",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "sprayOz",
            "in": "query",
            "schema": {
              "type": "number"
            },
            "description": "Spray container size in ounces."
          },
          {
            "name": "flags",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated product flags."
          },
          {
            "name": "originState",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "State the package ships from. Omit to assume interstate."
          },
          {
            "name": "carriers",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated carriers. Omit to assume any, including USPS."
          },
          {
            "name": "text",
            "in": "query",
            "schema": {
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "0 omits statute text."
          },
          {
            "name": "includeDrafts",
            "in": "query",
            "schema": {
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "false: verdict.enforced uses reviewed rules only. Default: draft rules included."
          }
        ],
        "responses": {
          "200": {
            "description": "Lookup result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/check": {
      "post": {
        "summary": "Verdicts for up to 50 products to one destination",
        "parameters": [
          {
            "name": "strict",
            "in": "query",
            "schema": {
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "true returns HTTP 422 (same body) when the decision is block."
          },
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One verdict per item (draft rules included unless includeDrafts is false)",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "422": {
            "description": "strict=true and at least one item is blocked",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/check/batch": {
      "post": {
        "summary": "Up to 100 checks, each with its own address and product",
        "description": "Counts as one request toward your quota; max 100 items. A bad item returns {id, error} without failing the others.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result or error per item, in order",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/ingredients": {
      "post": {
        "summary": "Cosmetic ingredient restrictions by state, with full law text",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ingredients"
                ],
                "properties": {
                  "ingredients": {
                    "type": "string",
                    "description": "Label ingredient list, comma-separated",
                    "example": "Water, Glycerin, PTFE, Formaldehyde"
                  },
                  "state": {
                    "type": "string",
                    "example": "CA",
                    "description": "Two-letter state; omit for every state covered"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Findings per ingredient and rule",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IngredientsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/ingredients/batch": {
      "post": {
        "summary": "Up to 100 ingredient lists, each with an optional state; full findings as /v1/ingredients",
        "description": "Counts as one request toward your quota. A bad item returns {id, error} without failing the others.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "object",
                      "required": [
                        "ingredients"
                      ],
                      "properties": {
                        "id": {
                          "type": [
                            "string",
                            "number"
                          ]
                        },
                        "ingredients": {
                          "type": "string",
                          "maxLength": 20000
                        },
                        "state": {
                          "type": "string",
                          "example": "CA"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ asOf, covered, disclaimer, results: [{ id, jurisdiction, researched, ingredientCount, general, findings } | { id, error }] }",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/matrix": {
      "post": {
        "summary": "Restriction table: up to 200 products × every state, plus ZIP-prefix city rows where the answer differs",
        "description": "For shipping platforms (ShipperHQ, Zonos, EasyPost) that keep their own restriction rules. Same engine and inputs as /v1/check. Counts as one request toward your quota.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "csv returns text/csv with one row per product × jurisdiction: ref, jurisdiction, name, level (state or city), state, zip_prefixes, decision, minimum_age, ship, avoid_carriers, licenses_needed, codes, coverage, error. Lists are space-separated."
          },
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MatrixRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One cell per state for each product",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MatrixResponse"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/laws": {
      "get": {
        "summary": "Search the law library",
        "parameters": [
          {
            "name": "jurisdiction",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated, e.g. US,US-NY"
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Text search over citation, title and text"
          },
          {
            "name": "text",
            "in": "query",
            "schema": {
              "enum": [
                "0",
                "1"
              ]
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paged laws",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "laws": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Law"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/laws/{lawId}": {
      "get": {
        "summary": "One law with the rules drawn from it",
        "parameters": [
          {
            "name": "lawId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Law",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Law"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/product-types": {
      "get": {
        "summary": "Product types /v1/check accepts as productType, with their category, flags and coverage status",
        "responses": {
          "200": {
            "description": "{ groups, productTypes }"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/flags": {
      "get": {
        "summary": "The product flag vocabulary (id, description, group)",
        "responses": {
          "200": {
            "description": "{ flags }"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/coverage": {
      "get": {
        "summary": "What we've researched: per topic and jurisdiction, restricted / no_restriction_found / not_checked",
        "parameters": [
          {
            "name": "topic",
            "in": "query",
            "description": "Comma-separated topics (default all)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Two-letter state; returns that state and federal only",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ rulesetVersion, coverage }"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/changes": {
      "get": {
        "summary": "Rule changes in each published version after `since` (at most the last 20 versions)",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "description": "Ruleset version you last saw (default: current - 1)",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ current, since, versions: [{ from, to, publishedAt, changes }] }"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/checks": {
      "get": {
        "summary": "Your decision log: every /v1/check and batch call from this key for 90 days (inputs, ruleset version, reason codes, citations)",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "before",
            "in": "query",
            "description": "The `next` value from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ checks: [...], next }, newest first"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/checks/export": {
      "get": {
        "summary": "Export your decision log between two dates, oldest first (at most 10,000 checks per call)",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "First day, YYYY-MM-DD (UTC)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Last day, YYYY-MM-DD (UTC), inclusive",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "The `next` value (JSON) or `Legal-To-Ship-Export-Next` header (CSV) from a cut-off export",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON `{ from, to, count, next, checks }`, or CSV with columns at, checkId, endpoint, ref, decision, codes, ruleIds, citations, rulesetVersion, request, adjustedBy, originalDecision (one row per item; lists joined with \"; \"; the last two only when your own rule feedback changed the decision)",
            "headers": {
              "Legal-To-Ship-Export-Next": {
                "schema": {
                  "type": "string"
                },
                "description": "CSV only: set when the export was cut off"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/purchases/check": {
      "post": {
        "summary": "Purchase caps: how much of each multi-order limit (e.g. 12 nine-liter cases per resident per year) the buyer has left",
        "description": "Sums the buyer's purchases recorded with POST /v1/purchases (this API key, last 400 days) against every cap of every capped rule that covers each item at the destination (a rule may carry several caps, some only for certain products; all must pass). Items in one request count as one order. A cap never blocks shipping by itself; use /v1/check for that. `buyer` is your opaque customer id or a sha256 hex of the trimmed, lowercased email: never the email (rejected). We hash it again with a random per-key salt before storage.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PurchaseRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Per item, every applicable cap with what's left",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PurchaseCapsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/purchases": {
      "post": {
        "summary": "Record a completed sale so it counts toward the buyer's purchase caps (register)",
        "description": "Same body as /v1/purchases/check plus orderId (and soldAt for a past sale). Kept 400 days. Returns the caps as of the sale; an over-cap sale is still recorded. 409 if the orderId is already recorded.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/PurchaseRequest"
                  },
                  {
                    "type": "object",
                    "required": [
                      "orderId"
                    ],
                    "properties": {
                      "orderId": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9_.:-]{1,128}$"
                      },
                      "soldAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Within the last 400 days; default now"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recorded",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PurchaseCapsResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "recorded": {
                          "const": true
                        },
                        "orderId": {
                          "type": "string"
                        },
                        "soldAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "expiresAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/purchases/{orderId}": {
      "delete": {
        "summary": "Remove a refunded or cancelled sale from the buyer's purchase caps (deregister)",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "responses": {
          "200": {
            "description": "{ deleted: true, orderId }"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/catalog": {
      "put": {
        "summary": "Save your product catalog (replace) so law-change alerts and webhooks name your affected SKUs",
        "description": "One catalog per account or client workspace, shared by all its keys (test keys have their own, never alerted). Up to 5,000 items and 5 MB. Items are validated as in /v1/check; the first bad item fails the request (400, naming its index and SKU) and the saved catalog is unchanged. Only product facts are stored: other fields are dropped. originState, carriers and licenses are the shipping context the catalog is checked with. 403 for keys created before saved catalogs: rotate the key.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CatalogRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ count, updatedAt, replaced: true, originState?, carriers?, licenses? }",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "413": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "summary": "Your saved catalog, a page at a time, with the latest ruleset's impact on it",
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 500
            }
          },
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "responses": {
          "200": {
            "description": "Saved items; pass `next` as the next offset until it is null",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "delete": {
        "summary": "Delete your saved catalog and its impact report",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "responses": {
          "200": {
            "description": "{ deleted: boolean }",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/feedback": {
      "post": {
        "summary": "Report a rule as wrong for you; the change applies to your own keys at once and goes to review",
        "description": "The requested change (disable, another effect, or only some product types/flags) applies right away to every key of your account or client workspace: check, batch, matrix, rules and purchase caps. Those answers carry adjustedBy and original; the decision log keeps the original verdict. We review the report; if approved, the rule is fixed for everyone in a later ruleset and your change becomes `superseded`. Up to 20 reports a day and 100 changes in force. No customer data: notes with email addresses are refused.",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ feedback }",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "feedback": {
                      "$ref": "#/components/schemas/Feedback"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      },
      "get": {
        "summary": "Your rule reports, newest first, with status and whether each change is in force",
        "parameters": [
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "responses": {
          "200": {
            "description": "{ feedback, max }",
            "headers": {
              "Legal-To-Ship-Version": {
                "schema": {
                  "type": "string",
                  "example": "2026-10-24"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "feedback": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Feedback"
                      }
                    },
                    "max": {
                      "type": "integer",
                      "description": "Changes in force allowed"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/feedback/{feedbackId}": {
      "delete": {
        "summary": "Undo your change: the published rule applies to your keys again at once (the report stays in review)",
        "parameters": [
          {
            "name": "feedbackId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^fb_[0-9A-Za-z]{12}$"
            }
          },
          {
            "name": "Legal-To-Ship-Version",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "2026-10-24"
            },
            "description": "Optional API version date. Unknown values are ignored; the response header says which version answered."
          }
        ],
        "responses": {
          "200": {
            "description": "{ feedback }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "feedback": {
                      "$ref": "#/components/schemas/Feedback"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "404": {
            "$ref": "#/components/responses/Error"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/ruleset": {
      "get": {
        "summary": "Current ruleset version and counts",
        "responses": {
          "200": {
            "description": "Ruleset info"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/classify": {
      "post": {
        "summary": "Product attributes from a listing (AI on paid plans; heuristics otherwise)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "specs": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Classification with confidence and needsReview"
          },
          "400": {
            "$ref": "#/components/responses/Error"
          },
          "403": {
            "description": "Missing or invalid API key"
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded"
          },
          "500": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "responses": {
      "Error": {
        "description": "Error",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                }
              },
              "required": [
                "error"
              ]
            }
          }
        }
      }
    },
    "schemas": {
      "CatalogItem": {
        "type": "object",
        "required": [
          "sku"
        ],
        "description": "productType, attributes, or both (as in /v1/check). Other fields are dropped.",
        "properties": {
          "sku": {
            "type": "string",
            "maxLength": 128
          },
          "title": {
            "type": "string",
            "maxLength": 300
          },
          "productType": {
            "type": "string",
            "example": "folding_knife"
          },
          "attributes": {
            "$ref": "#/components/schemas/Product"
          },
          "flags": {
            "type": "array",
            "items": {
              "enum": [
                "ballistic_knife",
                "metal_knuckle",
                "knuckle_knife",
                "throwing_star",
                "cane_sword",
                "belt_buckle",
                "lipstick_case_knife",
                "writing_pen_knife",
                "air_gauge_knife",
                "undetectable",
                "bowie",
                "blackjack",
                "slungshot",
                "sand_club",
                "nunchaku",
                "locked_draw_case",
                "spray_over_0_75_oz",
                "net_weight_over_2_5_oz",
                "not_pocket_sized",
                "not_personal_protection_size",
                "fogger_area_dispersal",
                "projectile",
                "non_aerosol",
                "contains_tear_gas_cn",
                "contains_tear_gas_cs",
                "unauthorized_compound",
                "lacks_ca_tear_gas_label",
                "no_serial_number",
                "no_use_instructions",
                "no_expiration_date",
                "ammunition",
                "handgun_ammunition",
                "ammo_components",
                "armor_piercing_ammunition",
                "explosive_incendiary_ammunition",
                "teflon_coated_bullet",
                "dragons_breath_shell",
                "flechette_or_bolo_shell",
                "magazine_over_10",
                "magazine_over_15",
                "magazine_over_17",
                "handgun_magazine",
                "long_gun_magazine",
                "magazine_parts_kit",
                "shotgun_ammunition",
                "shotgun_magazine_extension",
                "baton",
                "sap_glove",
                "kubotan",
                "sword",
                "oc_over_18_percent",
                "contains_tear_gas_cs_aerosol",
                "tear_gas_over_2_percent",
                "no_manufacturer_name",
                "non_metal_knuckle",
                "air_gun",
                "airsoft",
                "paintball_marker",
                "imitation_firearm",
                "realistic_appearance",
                "lacks_federal_orange_marking",
                "lacks_ca_airsoft_fluorescent_markings",
                "caliber_over_177",
                "muzzle_velocity_700fps_plus",
                "muzzle_velocity_400fps_plus",
                "concealable_air_gun",
                "body_armor",
                "crossbow",
                "consumer_fireworks",
                "aerial_fireworks",
                "sparklers_novelties",
                "wire_sparklers",
                "banned_audible_fireworks",
                "laser_pointer",
                "laser_over_5mw",
                "wine",
                "beer",
                "spirits",
                "alcohol_from_producer",
                "alcohol_from_retailer",
                "firearm",
                "handgun",
                "long_gun",
                "semiauto_rifle",
                "semiauto_detachable_magazine",
                "assault_weapon",
                "assault_weapon_attachment",
                "unfinished_frame_receiver",
                "frame_receiver_jig",
                "weapon_parts_kit",
                "firearm_3d_print_file",
                "firearm_manufacturing_machine",
                "firearm_barrel",
                "suppressor",
                "suppressor_part",
                "solvent_trap",
                "rapid_fire_device",
                "binary_trigger",
                "forced_reset_trigger",
                "machinegun_conversion_device",
                "pistol_brace",
                "convertible_pistol",
                "vape",
                "contains_nicotine",
                "cigarettes",
                "roll_your_own",
                "cigars",
                "pipe_tobacco",
                "smokeless_tobacco",
                "nicotine_pouch",
                "flavored",
                "menthol",
                "flavor_not_menthol",
                "not_on_state_directory",
                "on_state_prohibited_list",
                "no_fda_pmta_status",
                "foreign_adversary_origin",
                "youth_appealing_design",
                "contains_other_psychoactive",
                "nicotine_analogue",
                "nicotine_over_35_mg_ml",
                "nicotine_over_75_mg_ml",
                "hemp_intoxicating",
                "hemp_delta9_edible",
                "cbd_product",
                "smokable_hemp",
                "thca_flower",
                "cbd_food_or_beverage",
                "hemp_synthetic_cannabinoid",
                "hemp_converted_cannabinoid",
                "hemp_thc_beverage",
                "hemp_vape",
                "hemp_preroll",
                "hemp_flower",
                "hemp_topical",
                "cbd_full_spectrum",
                "cbd_thc_free",
                "kratom",
                "seven_oh_mitragynine",
                "mitragynine_pseudoindoxyl",
                "kratom_extract",
                "kratom_inhalable",
                "kratom_vape",
                "kratom_food_or_beverage",
                "kratom_confection",
                "kratom_synthetic_alkaloid",
                "lithium_battery_loose",
                "lithium_battery_in_equipment",
                "power_bank",
                "lithium_battery_over_100wh",
                "flammable_aerosol",
                "flammable_liquid_cosmetic",
                "flammable_liquid_low_flashpoint",
                "matches",
                "strike_anywhere_matches",
                "lighter",
                "butane_refill",
                "dry_ice",
                "amanita_muscaria",
                "amanita_conventional_food",
                "psilocybin_spores",
                "salvia_divinorum",
                "salvia_extract",
                "blue_lotus",
                "kanna",
                "dietary_supplement",
                "weight_loss_supplement",
                "muscle_building_supplement",
                "tianeptine",
                "phenibut",
                "dmaa_or_dmha",
                "ephedra",
                "pure_powdered_caffeine",
                "kava",
                "nitrous_oxide_charger",
                "nitrous_oxide_tank",
                "flavored_nitrous_oxide",
                "cracker_dispenser",
                "aerosol_spray_paint",
                "broad_tip_marker",
                "etching_product",
                "flipper_knife",
                "karambit",
                "neck_knife",
                "boot_knife",
                "bayonet",
                "marketed_for_self_defense",
                "air_gun_pistol_grip",
                "emissions_part_no_carb_eo",
                "emissions_defeat_device",
                "gas_small_offroad_engine",
                "portable_generator_gas",
                "voc_noncompliant_consumer_product",
                "catalytic_converter",
                "used_catalytic_converter",
                "sunscreen",
                "oxybenzone",
                "octinoxate",
                "avobenzone",
                "octocrylene",
                "non_mineral_sunscreen",
                "aminobenzoic_acid",
                "trolamine_salicylate",
                "no_fda_marketing_order",
                "box_cutter",
                "pfas_intentionally_added",
                "pfas_cookware",
                "pfas_textile_apparel",
                "pfas_outdoor_apparel",
                "pfas_intimate_apparel",
                "pfas_textile_furnishing",
                "pfas_upholstered_furniture",
                "pfas_juvenile_product",
                "pfas_carpet_rug",
                "pfas_fabric_treatment",
                "pfas_ski_wax",
                "pfas_dental_floss",
                "pfas_menstrual_product",
                "pfas_incontinence_product",
                "pfas_cleaning_product",
                "pfas_food_packaging",
                "pfas_artificial_turf",
                "cider"
              ]
            },
            "description": "Added to the attributes' flags"
          }
        }
      },
      "CatalogRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "maxItems": 5000,
            "items": {
              "$ref": "#/components/schemas/CatalogItem"
            }
          },
          "originState": {
            "type": "string",
            "example": "TX",
            "description": "Ship-from state the catalog is checked with"
          },
          "carriers": {
            "type": "array",
            "items": {
              "enum": [
                "usps",
                "ups",
                "fedex",
                "dhl",
                "other"
              ]
            }
          },
          "licenses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CatalogPage": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "offset": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "next": {
            "type": [
              "integer",
              "null"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogItem"
            }
          },
          "lastImpact": {
            "type": [
              "object",
              "null"
            ],
            "description": "What the latest ruleset publish changed for this catalog",
            "properties": {
              "version": {
                "type": "integer"
              },
              "from": {
                "type": "integer"
              },
              "publishedAt": {
                "type": "string"
              },
              "skus": {
                "type": "integer",
                "description": "Distinct SKUs affected"
              },
              "total": {
                "type": "integer",
                "description": "SKU × jurisdiction changes"
              },
              "draftTotal": {
                "type": "integer",
                "description": "Of total, changes resting on a draft rule (not yet reviewed)"
              },
              "lines": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Plain-text summary, as in the alert email"
              }
            }
          }
        }
      },
      "Product": {
        "type": "object",
        "required": [
          "category",
          "mechanism"
        ],
        "properties": {
          "category": {
            "enum": [
              "folding_knife",
              "fixed_blade",
              "balisong",
              "pepper_spray",
              "stun_gun",
              "other"
            ]
          },
          "mechanism": {
            "enum": [
              "manual",
              "assisted",
              "automatic",
              "otf",
              "gravity",
              "fixed",
              "none"
            ]
          },
          "bladeLengthIn": {
            "type": [
              "number",
              "null"
            ]
          },
          "edge": {
            "enum": [
              "single",
              "double",
              "none"
            ]
          },
          "style": {
            "enum": [
              "standard",
              "dagger",
              "dirk",
              "stiletto",
              "throwing",
              "none"
            ]
          },
          "flags": {
            "type": "array",
            "items": {
              "enum": [
                "ballistic_knife",
                "metal_knuckle",
                "knuckle_knife",
                "throwing_star",
                "cane_sword",
                "belt_buckle",
                "lipstick_case_knife",
                "writing_pen_knife",
                "air_gauge_knife",
                "undetectable",
                "bowie",
                "blackjack",
                "slungshot",
                "sand_club",
                "nunchaku",
                "locked_draw_case",
                "spray_over_0_75_oz",
                "net_weight_over_2_5_oz",
                "not_pocket_sized",
                "not_personal_protection_size",
                "fogger_area_dispersal",
                "projectile",
                "non_aerosol",
                "contains_tear_gas_cn",
                "contains_tear_gas_cs",
                "unauthorized_compound",
                "lacks_ca_tear_gas_label",
                "no_serial_number",
                "no_use_instructions",
                "no_expiration_date",
                "ammunition",
                "handgun_ammunition",
                "ammo_components",
                "armor_piercing_ammunition",
                "explosive_incendiary_ammunition",
                "teflon_coated_bullet",
                "dragons_breath_shell",
                "flechette_or_bolo_shell",
                "magazine_over_10",
                "magazine_over_15",
                "magazine_over_17",
                "handgun_magazine",
                "long_gun_magazine",
                "magazine_parts_kit",
                "shotgun_ammunition",
                "shotgun_magazine_extension",
                "baton",
                "sap_glove",
                "kubotan",
                "sword",
                "oc_over_18_percent",
                "contains_tear_gas_cs_aerosol",
                "tear_gas_over_2_percent",
                "no_manufacturer_name",
                "non_metal_knuckle",
                "air_gun",
                "airsoft",
                "paintball_marker",
                "imitation_firearm",
                "realistic_appearance",
                "lacks_federal_orange_marking",
                "lacks_ca_airsoft_fluorescent_markings",
                "caliber_over_177",
                "muzzle_velocity_700fps_plus",
                "muzzle_velocity_400fps_plus",
                "concealable_air_gun",
                "body_armor",
                "crossbow",
                "consumer_fireworks",
                "aerial_fireworks",
                "sparklers_novelties",
                "wire_sparklers",
                "banned_audible_fireworks",
                "laser_pointer",
                "laser_over_5mw",
                "wine",
                "beer",
                "spirits",
                "alcohol_from_producer",
                "alcohol_from_retailer",
                "firearm",
                "handgun",
                "long_gun",
                "semiauto_rifle",
                "semiauto_detachable_magazine",
                "assault_weapon",
                "assault_weapon_attachment",
                "unfinished_frame_receiver",
                "frame_receiver_jig",
                "weapon_parts_kit",
                "firearm_3d_print_file",
                "firearm_manufacturing_machine",
                "firearm_barrel",
                "suppressor",
                "suppressor_part",
                "solvent_trap",
                "rapid_fire_device",
                "binary_trigger",
                "forced_reset_trigger",
                "machinegun_conversion_device",
                "pistol_brace",
                "convertible_pistol",
                "vape",
                "contains_nicotine",
                "cigarettes",
                "roll_your_own",
                "cigars",
                "pipe_tobacco",
                "smokeless_tobacco",
                "nicotine_pouch",
                "flavored",
                "menthol",
                "flavor_not_menthol",
                "not_on_state_directory",
                "on_state_prohibited_list",
                "no_fda_pmta_status",
                "foreign_adversary_origin",
                "youth_appealing_design",
                "contains_other_psychoactive",
                "nicotine_analogue",
                "nicotine_over_35_mg_ml",
                "nicotine_over_75_mg_ml",
                "hemp_intoxicating",
                "hemp_delta9_edible",
                "cbd_product",
                "smokable_hemp",
                "thca_flower",
                "cbd_food_or_beverage",
                "hemp_synthetic_cannabinoid",
                "hemp_converted_cannabinoid",
                "hemp_thc_beverage",
                "hemp_vape",
                "hemp_preroll",
                "hemp_flower",
                "hemp_topical",
                "cbd_full_spectrum",
                "cbd_thc_free",
                "kratom",
                "seven_oh_mitragynine",
                "mitragynine_pseudoindoxyl",
                "kratom_extract",
                "kratom_inhalable",
                "kratom_vape",
                "kratom_food_or_beverage",
                "kratom_confection",
                "kratom_synthetic_alkaloid",
                "lithium_battery_loose",
                "lithium_battery_in_equipment",
                "power_bank",
                "lithium_battery_over_100wh",
                "flammable_aerosol",
                "flammable_liquid_cosmetic",
                "flammable_liquid_low_flashpoint",
                "matches",
                "strike_anywhere_matches",
                "lighter",
                "butane_refill",
                "dry_ice",
                "amanita_muscaria",
                "amanita_conventional_food",
                "psilocybin_spores",
                "salvia_divinorum",
                "salvia_extract",
                "blue_lotus",
                "kanna",
                "dietary_supplement",
                "weight_loss_supplement",
                "muscle_building_supplement",
                "tianeptine",
                "phenibut",
                "dmaa_or_dmha",
                "ephedra",
                "pure_powdered_caffeine",
                "kava",
                "nitrous_oxide_charger",
                "nitrous_oxide_tank",
                "flavored_nitrous_oxide",
                "cracker_dispenser",
                "aerosol_spray_paint",
                "broad_tip_marker",
                "etching_product",
                "flipper_knife",
                "karambit",
                "neck_knife",
                "boot_knife",
                "bayonet",
                "marketed_for_self_defense",
                "air_gun_pistol_grip",
                "emissions_part_no_carb_eo",
                "emissions_defeat_device",
                "gas_small_offroad_engine",
                "portable_generator_gas",
                "voc_noncompliant_consumer_product",
                "catalytic_converter",
                "used_catalytic_converter",
                "sunscreen",
                "oxybenzone",
                "octinoxate",
                "avobenzone",
                "octocrylene",
                "non_mineral_sunscreen",
                "aminobenzoic_acid",
                "trolamine_salicylate",
                "no_fda_marketing_order",
                "box_cutter",
                "pfas_intentionally_added",
                "pfas_cookware",
                "pfas_textile_apparel",
                "pfas_outdoor_apparel",
                "pfas_intimate_apparel",
                "pfas_textile_furnishing",
                "pfas_upholstered_furniture",
                "pfas_juvenile_product",
                "pfas_carpet_rug",
                "pfas_fabric_treatment",
                "pfas_ski_wax",
                "pfas_dental_floss",
                "pfas_menstrual_product",
                "pfas_incontinence_product",
                "pfas_cleaning_product",
                "pfas_food_packaging",
                "pfas_artificial_turf",
                "cider"
              ]
            }
          },
          "sprayOz": {
            "type": [
              "number",
              "null"
            ],
            "description": "Spray container size in ounces"
          }
        }
      },
      "CheckRequest": {
        "type": "object",
        "required": [
          "destination",
          "items"
        ],
        "properties": {
          "destination": {
            "type": "object",
            "required": [
              "country"
            ],
            "properties": {
              "country": {
                "type": "string",
                "example": "US"
              },
              "province": {
                "type": "string",
                "example": "NY"
              },
              "zip": {
                "type": "string",
                "example": "10001"
              }
            }
          },
          "originState": {
            "type": "string",
            "example": "TX"
          },
          "carriers": {
            "type": "array",
            "items": {
              "enum": [
                "usps",
                "ups",
                "fedex",
                "dhl",
                "other"
              ]
            }
          },
          "platforms": {
            "type": "array",
            "items": {
              "enum": [
                "shopify",
                "shopify_payments",
                "stripe",
                "paypal",
                "square",
                "amazon",
                "ebay",
                "etsy",
                "walmart",
                "tiktok_shop"
              ]
            },
            "description": "Where you sell or take payment. Adds those platforms' prohibited/restricted-product policies (code PLATFORM_POLICY). Omitted = no platform policies."
          },
          "licenses": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "License ids you hold or buyer credentials you check before shipping (e.g. il-foid). See actions.licensesNeeded."
          },
          "includeDrafts": {
            "type": "boolean",
            "description": "Default true: draft rules (not yet reviewed by a lawyer) decide too, labelled basis \"draft\". false: reviewed rules only, and each result carries a drafts preview. Changed 2026-11-02 (drafts used to be off by default)."
          },
          "storeRules": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/StoreRule"
            },
            "description": "Your own restrictions on top of the law, applied to this request only. Matches come back with code STORE_POLICY."
          },
          "items": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "description": "Send productType (from GET /v1/product-types), or attributes with category and mechanism. With both, attributes add to the type (blade length, size, extra flags).",
              "properties": {
                "ref": {
                  "type": "string"
                },
                "productType": {
                  "type": "string",
                  "example": "wine_producer"
                },
                "attributes": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          }
        }
      },
      "Reason": {
        "type": "object",
        "properties": {
          "ruleId": {
            "type": "string"
          },
          "code": {
            "enum": [
              "PLATFORM_POLICY",
              "CARRIER_RESTRICTED",
              "BLOCKED_INTERSTATE",
              "BLOCKED_SPRAY_SIZE",
              "BLOCKED_AUTOMATIC_KNIFE",
              "BLOCKED_GRAVITY_KNIFE",
              "BLOCKED_ASSISTED_KNIFE",
              "BLOCKED_BLADE_LENGTH",
              "BLOCKED_BALLISTIC_KNIFE",
              "BLOCKED_KNUCKLES",
              "BLOCKED_DISGUISED_KNIFE",
              "BLOCKED_THROWING_STAR",
              "BLOCKED_SPRAY_FORMULA",
              "BLOCKED_SPRAY_LABELING",
              "BLOCKED_SPRAY_TYPE",
              "BLOCKED_BALISONG",
              "BLOCKED_PEPPER_SPRAY",
              "BLOCKED_STUN_GUN",
              "BLOCKED_BLADE_STYLE",
              "BLOCKED_PROHIBITED_ITEM",
              "BLOCKED",
              "AGE_16",
              "AGE_18",
              "AGE_19",
              "AGE_21",
              "LICENSE_REQUIRED",
              "STORE_POLICY"
            ],
            "description": "Stable machine-readable reason, derived from the rule's effect and conditions"
          },
          "effect": {
            "enum": [
              "block",
              "age16",
              "age18",
              "age19",
              "age21"
            ]
          },
          "jurisdiction": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "citation": {
            "type": "string"
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri"
          },
          "lastVerified": {
            "type": "string",
            "description": "YYYY-MM-DD of the lawyer review; empty for a draft"
          },
          "basis": {
            "$ref": "#/components/schemas/Basis"
          },
          "adjustedBy": {
            "type": "string",
            "description": "Set when your own rule feedback changed this rule: \"your feedback fb_…\""
          }
        }
      },
      "Basis": {
        "enum": [
          "draft",
          "reviewed"
        ],
        "description": "draft: written from the official law text, not yet reviewed by a lawyer (applied unless includeDrafts is false). reviewed: checked by a lawyer. For a result: draft when any rule behind it is. Accuracy isn't guaranteed either way."
      },
      "Original": {
        "type": "object",
        "description": "The answer without your own rule feedback (also kept in your decision log)",
        "properties": {
          "decision": {
            "enum": [
              "allow",
              "block",
              "age_verify"
            ]
          },
          "minimumAge": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ruleIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RuleChange": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "disable"
              }
            },
            "description": "The rule no longer applies to you"
          },
          {
            "type": "object",
            "required": [
              "type",
              "effect"
            ],
            "properties": {
              "type": {
                "const": "effect"
              },
              "effect": {
                "enum": [
                  "block",
                  "age16",
                  "age18",
                  "age19",
                  "age21"
                ]
              }
            },
            "description": "The rule applies with this effect instead"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "only_for"
              },
              "productTypes": {
                "type": "array",
                "maxItems": 20,
                "items": {
                  "type": "string"
                }
              },
              "flags": {
                "type": "array",
                "maxItems": 20,
                "items": {
                  "enum": [
                    "ballistic_knife",
                    "metal_knuckle",
                    "knuckle_knife",
                    "throwing_star",
                    "cane_sword",
                    "belt_buckle",
                    "lipstick_case_knife",
                    "writing_pen_knife",
                    "air_gauge_knife",
                    "undetectable",
                    "bowie",
                    "blackjack",
                    "slungshot",
                    "sand_club",
                    "nunchaku",
                    "locked_draw_case",
                    "spray_over_0_75_oz",
                    "net_weight_over_2_5_oz",
                    "not_pocket_sized",
                    "not_personal_protection_size",
                    "fogger_area_dispersal",
                    "projectile",
                    "non_aerosol",
                    "contains_tear_gas_cn",
                    "contains_tear_gas_cs",
                    "unauthorized_compound",
                    "lacks_ca_tear_gas_label",
                    "no_serial_number",
                    "no_use_instructions",
                    "no_expiration_date",
                    "ammunition",
                    "handgun_ammunition",
                    "ammo_components",
                    "armor_piercing_ammunition",
                    "explosive_incendiary_ammunition",
                    "teflon_coated_bullet",
                    "dragons_breath_shell",
                    "flechette_or_bolo_shell",
                    "magazine_over_10",
                    "magazine_over_15",
                    "magazine_over_17",
                    "handgun_magazine",
                    "long_gun_magazine",
                    "magazine_parts_kit",
                    "shotgun_ammunition",
                    "shotgun_magazine_extension",
                    "baton",
                    "sap_glove",
                    "kubotan",
                    "sword",
                    "oc_over_18_percent",
                    "contains_tear_gas_cs_aerosol",
                    "tear_gas_over_2_percent",
                    "no_manufacturer_name",
                    "non_metal_knuckle",
                    "air_gun",
                    "airsoft",
                    "paintball_marker",
                    "imitation_firearm",
                    "realistic_appearance",
                    "lacks_federal_orange_marking",
                    "lacks_ca_airsoft_fluorescent_markings",
                    "caliber_over_177",
                    "muzzle_velocity_700fps_plus",
                    "muzzle_velocity_400fps_plus",
                    "concealable_air_gun",
                    "body_armor",
                    "crossbow",
                    "consumer_fireworks",
                    "aerial_fireworks",
                    "sparklers_novelties",
                    "wire_sparklers",
                    "banned_audible_fireworks",
                    "laser_pointer",
                    "laser_over_5mw",
                    "wine",
                    "beer",
                    "spirits",
                    "alcohol_from_producer",
                    "alcohol_from_retailer",
                    "firearm",
                    "handgun",
                    "long_gun",
                    "semiauto_rifle",
                    "semiauto_detachable_magazine",
                    "assault_weapon",
                    "assault_weapon_attachment",
                    "unfinished_frame_receiver",
                    "frame_receiver_jig",
                    "weapon_parts_kit",
                    "firearm_3d_print_file",
                    "firearm_manufacturing_machine",
                    "firearm_barrel",
                    "suppressor",
                    "suppressor_part",
                    "solvent_trap",
                    "rapid_fire_device",
                    "binary_trigger",
                    "forced_reset_trigger",
                    "machinegun_conversion_device",
                    "pistol_brace",
                    "convertible_pistol",
                    "vape",
                    "contains_nicotine",
                    "cigarettes",
                    "roll_your_own",
                    "cigars",
                    "pipe_tobacco",
                    "smokeless_tobacco",
                    "nicotine_pouch",
                    "flavored",
                    "menthol",
                    "flavor_not_menthol",
                    "not_on_state_directory",
                    "on_state_prohibited_list",
                    "no_fda_pmta_status",
                    "foreign_adversary_origin",
                    "youth_appealing_design",
                    "contains_other_psychoactive",
                    "nicotine_analogue",
                    "nicotine_over_35_mg_ml",
                    "nicotine_over_75_mg_ml",
                    "hemp_intoxicating",
                    "hemp_delta9_edible",
                    "cbd_product",
                    "smokable_hemp",
                    "thca_flower",
                    "cbd_food_or_beverage",
                    "hemp_synthetic_cannabinoid",
                    "hemp_converted_cannabinoid",
                    "hemp_thc_beverage",
                    "hemp_vape",
                    "hemp_preroll",
                    "hemp_flower",
                    "hemp_topical",
                    "cbd_full_spectrum",
                    "cbd_thc_free",
                    "kratom",
                    "seven_oh_mitragynine",
                    "mitragynine_pseudoindoxyl",
                    "kratom_extract",
                    "kratom_inhalable",
                    "kratom_vape",
                    "kratom_food_or_beverage",
                    "kratom_confection",
                    "kratom_synthetic_alkaloid",
                    "lithium_battery_loose",
                    "lithium_battery_in_equipment",
                    "power_bank",
                    "lithium_battery_over_100wh",
                    "flammable_aerosol",
                    "flammable_liquid_cosmetic",
                    "flammable_liquid_low_flashpoint",
                    "matches",
                    "strike_anywhere_matches",
                    "lighter",
                    "butane_refill",
                    "dry_ice",
                    "amanita_muscaria",
                    "amanita_conventional_food",
                    "psilocybin_spores",
                    "salvia_divinorum",
                    "salvia_extract",
                    "blue_lotus",
                    "kanna",
                    "dietary_supplement",
                    "weight_loss_supplement",
                    "muscle_building_supplement",
                    "tianeptine",
                    "phenibut",
                    "dmaa_or_dmha",
                    "ephedra",
                    "pure_powdered_caffeine",
                    "kava",
                    "nitrous_oxide_charger",
                    "nitrous_oxide_tank",
                    "flavored_nitrous_oxide",
                    "cracker_dispenser",
                    "aerosol_spray_paint",
                    "broad_tip_marker",
                    "etching_product",
                    "flipper_knife",
                    "karambit",
                    "neck_knife",
                    "boot_knife",
                    "bayonet",
                    "marketed_for_self_defense",
                    "air_gun_pistol_grip",
                    "emissions_part_no_carb_eo",
                    "emissions_defeat_device",
                    "gas_small_offroad_engine",
                    "portable_generator_gas",
                    "voc_noncompliant_consumer_product",
                    "catalytic_converter",
                    "used_catalytic_converter",
                    "sunscreen",
                    "oxybenzone",
                    "octinoxate",
                    "avobenzone",
                    "octocrylene",
                    "non_mineral_sunscreen",
                    "aminobenzoic_acid",
                    "trolamine_salicylate",
                    "no_fda_marketing_order",
                    "box_cutter",
                    "pfas_intentionally_added",
                    "pfas_cookware",
                    "pfas_textile_apparel",
                    "pfas_outdoor_apparel",
                    "pfas_intimate_apparel",
                    "pfas_textile_furnishing",
                    "pfas_upholstered_furniture",
                    "pfas_juvenile_product",
                    "pfas_carpet_rug",
                    "pfas_fabric_treatment",
                    "pfas_ski_wax",
                    "pfas_dental_floss",
                    "pfas_menstrual_product",
                    "pfas_incontinence_product",
                    "pfas_cleaning_product",
                    "pfas_food_packaging",
                    "pfas_artificial_turf",
                    "cider"
                  ]
                }
              }
            },
            "description": "The rule applies only to products of these types or with any of these flags"
          }
        ]
      },
      "FeedbackRequest": {
        "type": "object",
        "required": [
          "ruleId",
          "kind"
        ],
        "properties": {
          "ruleId": {
            "type": "string",
            "description": "A reasons[].ruleId from a check, or a rule id from GET /v1/rules. Not a store rule."
          },
          "kind": {
            "enum": [
              "doesnt_apply",
              "wrong_effect",
              "outdated",
              "other"
            ]
          },
          "change": {
            "$ref": "#/components/schemas/RuleChange"
          },
          "note": {
            "type": "string",
            "maxLength": 1000,
            "description": "What's wrong. No customer data; email addresses are refused. Required without change."
          },
          "contact": {
            "type": "string",
            "maxLength": 200,
            "description": "Optional: how to reach you"
          },
          "context": {
            "type": "object",
            "properties": {
              "state": {
                "type": "string"
              },
              "productType": {
                "type": "string"
              }
            },
            "description": "Optional: where it went wrong"
          }
        }
      },
      "Feedback": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^fb_[0-9A-Za-z]{12}$"
          },
          "ruleId": {
            "type": "string"
          },
          "lawId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The law record the rule was drawn from when reported"
          },
          "kind": {
            "enum": [
              "doesnt_apply",
              "wrong_effect",
              "outdated",
              "other"
            ]
          },
          "change": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/RuleChange"
              },
              {
                "type": "null"
              }
            ]
          },
          "note": {
            "type": "string"
          },
          "contact": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "enum": [
              "pending",
              "approved",
              "rejected",
              "superseded"
            ],
            "description": "superseded: a published fix for everyone replaced your change"
          },
          "applied": {
            "type": "boolean",
            "description": "Your change is in force for your keys"
          },
          "adjustedBy": {
            "type": "string",
            "description": "The label your adjusted answers carry while applied"
          },
          "undoneAt": {
            "type": "string",
            "format": "date-time"
          },
          "replacedBy": {
            "type": "string",
            "description": "A newer report on the same rule replaced this change"
          },
          "reviewedAt": {
            "type": "string",
            "format": "date-time"
          },
          "reviewNote": {
            "type": "string"
          }
        }
      },
      "Actions": {
        "type": "object",
        "description": "What the merchant should do. ship may be true for a block caused only by carrier rules: ship with a carrier not in avoidCarriers.",
        "properties": {
          "ship": {
            "type": "boolean"
          },
          "minimumAge": {
            "type": [
              "integer",
              "null"
            ]
          },
          "signature": {
            "type": [
              "object",
              "null"
            ],
            "description": "Adult-signature options to buy. Carrier adult signature checks 21+; USPS is only suggested for 21+ rules.",
            "properties": {
              "usps": {
                "const": "ADULT_SIGNATURE_RESTRICTED"
              },
              "fedex": {
                "const": "ADULT_SIGNATURE"
              },
              "ups": {
                "const": "ADULT_SIGNATURE"
              },
              "easypost": {
                "type": "object",
                "properties": {
                  "delivery_confirmation": {
                    "const": "ADULT_SIGNATURE"
                  }
                }
              }
            }
          },
          "avoidCarriers": {
            "type": "array",
            "items": {
              "enum": [
                "usps",
                "ups",
                "fedex",
                "dhl",
                "other"
              ]
            }
          },
          "licensesNeeded": {
            "type": "array",
            "description": "What would make a LICENSE_REQUIRED block shippable: a seller permit (holder seller) or a buyer credential to collect before shipping (holder buyer). Send its id in licenses once you have it.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "holder": {
                  "enum": [
                    "buyer",
                    "seller"
                  ]
                }
              }
            }
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CheckResult": {
        "type": "object",
        "properties": {
          "decision": {
            "enum": [
              "allow",
              "block",
              "age_verify"
            ]
          },
          "minimumAge": {
            "type": [
              "integer",
              "null"
            ]
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "One plain sentence to show a shopper at checkout; null when allowed"
          },
          "basis": {
            "$ref": "#/components/schemas/Basis"
          },
          "actions": {
            "$ref": "#/components/schemas/Actions"
          },
          "reasons": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reason"
            }
          },
          "drafts": {
            "type": "object",
            "description": "Only with includeDrafts: false: what the draft rules would decide",
            "properties": {
              "decision": {
                "enum": [
                  "allow",
                  "block",
                  "age_verify"
                ]
              },
              "minimumAge": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "codes": {
                "type": "array",
                "items": {
                  "enum": [
                    "PLATFORM_POLICY",
                    "CARRIER_RESTRICTED",
                    "BLOCKED_INTERSTATE",
                    "BLOCKED_SPRAY_SIZE",
                    "BLOCKED_AUTOMATIC_KNIFE",
                    "BLOCKED_GRAVITY_KNIFE",
                    "BLOCKED_ASSISTED_KNIFE",
                    "BLOCKED_BLADE_LENGTH",
                    "BLOCKED_BALLISTIC_KNIFE",
                    "BLOCKED_KNUCKLES",
                    "BLOCKED_DISGUISED_KNIFE",
                    "BLOCKED_THROWING_STAR",
                    "BLOCKED_SPRAY_FORMULA",
                    "BLOCKED_SPRAY_LABELING",
                    "BLOCKED_SPRAY_TYPE",
                    "BLOCKED_BALISONG",
                    "BLOCKED_PEPPER_SPRAY",
                    "BLOCKED_STUN_GUN",
                    "BLOCKED_BLADE_STYLE",
                    "BLOCKED_PROHIBITED_ITEM",
                    "BLOCKED",
                    "AGE_16",
                    "AGE_18",
                    "AGE_19",
                    "AGE_21",
                    "LICENSE_REQUIRED",
                    "STORE_POLICY"
                  ]
                }
              }
            }
          },
          "adjustedBy": {
            "type": "string",
            "description": "Set when your own rule feedback changed this answer"
          },
          "original": {
            "$ref": "#/components/schemas/Original"
          }
        }
      },
      "CheckResponse": {
        "type": "object",
        "properties": {
          "rulesetVersion": {
            "type": "integer"
          },
          "rulesAsOf": {
            "type": "string"
          },
          "basis": {
            "enum": [
              "verified",
              "verified+drafts"
            ],
            "description": "verified+drafts (default): draft rules decide too; verified: includeDrafts was false"
          },
          "disclaimer": {
            "type": "string"
          },
          "checkId": {
            "type": "string"
          },
          "decision": {
            "enum": [
              "allow",
              "block",
              "age_verify"
            ],
            "description": "The strictest item decision"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "The strictest item's checkout message"
          },
          "actions": {
            "$ref": "#/components/schemas/Actions"
          },
          "results": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/CheckResult"
                },
                {
                  "type": "object",
                  "properties": {
                    "ref": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "StoreRule": {
        "type": "object",
        "required": [
          "id",
          "label",
          "when",
          "effect"
        ],
        "description": "A merchant restriction. Give states (\"all\" or a list), zipPrefixes, or both (ZIPs within those states).",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{1,40}$",
            "example": "no-stun-ny"
          },
          "label": {
            "type": "string",
            "maxLength": 120,
            "description": "Returned as the reason's summary",
            "example": "We don't ship stun guns to New York"
          },
          "when": {
            "type": "object",
            "description": "Product condition; {} matches every product. Same fields as rule conditions.",
            "properties": {
              "categories": {
                "type": "array",
                "items": {
                  "enum": [
                    "folding_knife",
                    "fixed_blade",
                    "balisong",
                    "pepper_spray",
                    "stun_gun",
                    "other"
                  ]
                }
              },
              "mechanisms": {
                "type": "array",
                "items": {
                  "enum": [
                    "manual",
                    "assisted",
                    "automatic",
                    "otf",
                    "gravity",
                    "fixed",
                    "none"
                  ]
                }
              },
              "styles": {
                "type": "array",
                "items": {
                  "enum": [
                    "standard",
                    "dagger",
                    "dirk",
                    "stiletto",
                    "throwing",
                    "none"
                  ]
                }
              },
              "edges": {
                "type": "array",
                "items": {
                  "enum": [
                    "single",
                    "double",
                    "none"
                  ]
                }
              },
              "flagsAny": {
                "type": "array",
                "items": {
                  "enum": [
                    "ballistic_knife",
                    "metal_knuckle",
                    "knuckle_knife",
                    "throwing_star",
                    "cane_sword",
                    "belt_buckle",
                    "lipstick_case_knife",
                    "writing_pen_knife",
                    "air_gauge_knife",
                    "undetectable",
                    "bowie",
                    "blackjack",
                    "slungshot",
                    "sand_club",
                    "nunchaku",
                    "locked_draw_case",
                    "spray_over_0_75_oz",
                    "net_weight_over_2_5_oz",
                    "not_pocket_sized",
                    "not_personal_protection_size",
                    "fogger_area_dispersal",
                    "projectile",
                    "non_aerosol",
                    "contains_tear_gas_cn",
                    "contains_tear_gas_cs",
                    "unauthorized_compound",
                    "lacks_ca_tear_gas_label",
                    "no_serial_number",
                    "no_use_instructions",
                    "no_expiration_date",
                    "ammunition",
                    "handgun_ammunition",
                    "ammo_components",
                    "armor_piercing_ammunition",
                    "explosive_incendiary_ammunition",
                    "teflon_coated_bullet",
                    "dragons_breath_shell",
                    "flechette_or_bolo_shell",
                    "magazine_over_10",
                    "magazine_over_15",
                    "magazine_over_17",
                    "handgun_magazine",
                    "long_gun_magazine",
                    "magazine_parts_kit",
                    "shotgun_ammunition",
                    "shotgun_magazine_extension",
                    "baton",
                    "sap_glove",
                    "kubotan",
                    "sword",
                    "oc_over_18_percent",
                    "contains_tear_gas_cs_aerosol",
                    "tear_gas_over_2_percent",
                    "no_manufacturer_name",
                    "non_metal_knuckle",
                    "air_gun",
                    "airsoft",
                    "paintball_marker",
                    "imitation_firearm",
                    "realistic_appearance",
                    "lacks_federal_orange_marking",
                    "lacks_ca_airsoft_fluorescent_markings",
                    "caliber_over_177",
                    "muzzle_velocity_700fps_plus",
                    "muzzle_velocity_400fps_plus",
                    "concealable_air_gun",
                    "body_armor",
                    "crossbow",
                    "consumer_fireworks",
                    "aerial_fireworks",
                    "sparklers_novelties",
                    "wire_sparklers",
                    "banned_audible_fireworks",
                    "laser_pointer",
                    "laser_over_5mw",
                    "wine",
                    "beer",
                    "spirits",
                    "alcohol_from_producer",
                    "alcohol_from_retailer",
                    "firearm",
                    "handgun",
                    "long_gun",
                    "semiauto_rifle",
                    "semiauto_detachable_magazine",
                    "assault_weapon",
                    "assault_weapon_attachment",
                    "unfinished_frame_receiver",
                    "frame_receiver_jig",
                    "weapon_parts_kit",
                    "firearm_3d_print_file",
                    "firearm_manufacturing_machine",
                    "firearm_barrel",
                    "suppressor",
                    "suppressor_part",
                    "solvent_trap",
                    "rapid_fire_device",
                    "binary_trigger",
                    "forced_reset_trigger",
                    "machinegun_conversion_device",
                    "pistol_brace",
                    "convertible_pistol",
                    "vape",
                    "contains_nicotine",
                    "cigarettes",
                    "roll_your_own",
                    "cigars",
                    "pipe_tobacco",
                    "smokeless_tobacco",
                    "nicotine_pouch",
                    "flavored",
                    "menthol",
                    "flavor_not_menthol",
                    "not_on_state_directory",
                    "on_state_prohibited_list",
                    "no_fda_pmta_status",
                    "foreign_adversary_origin",
                    "youth_appealing_design",
                    "contains_other_psychoactive",
                    "nicotine_analogue",
                    "nicotine_over_35_mg_ml",
                    "nicotine_over_75_mg_ml",
                    "hemp_intoxicating",
                    "hemp_delta9_edible",
                    "cbd_product",
                    "smokable_hemp",
                    "thca_flower",
                    "cbd_food_or_beverage",
                    "hemp_synthetic_cannabinoid",
                    "hemp_converted_cannabinoid",
                    "hemp_thc_beverage",
                    "hemp_vape",
                    "hemp_preroll",
                    "hemp_flower",
                    "hemp_topical",
                    "cbd_full_spectrum",
                    "cbd_thc_free",
                    "kratom",
                    "seven_oh_mitragynine",
                    "mitragynine_pseudoindoxyl",
                    "kratom_extract",
                    "kratom_inhalable",
                    "kratom_vape",
                    "kratom_food_or_beverage",
                    "kratom_confection",
                    "kratom_synthetic_alkaloid",
                    "lithium_battery_loose",
                    "lithium_battery_in_equipment",
                    "power_bank",
                    "lithium_battery_over_100wh",
                    "flammable_aerosol",
                    "flammable_liquid_cosmetic",
                    "flammable_liquid_low_flashpoint",
                    "matches",
                    "strike_anywhere_matches",
                    "lighter",
                    "butane_refill",
                    "dry_ice",
                    "amanita_muscaria",
                    "amanita_conventional_food",
                    "psilocybin_spores",
                    "salvia_divinorum",
                    "salvia_extract",
                    "blue_lotus",
                    "kanna",
                    "dietary_supplement",
                    "weight_loss_supplement",
                    "muscle_building_supplement",
                    "tianeptine",
                    "phenibut",
                    "dmaa_or_dmha",
                    "ephedra",
                    "pure_powdered_caffeine",
                    "kava",
                    "nitrous_oxide_charger",
                    "nitrous_oxide_tank",
                    "flavored_nitrous_oxide",
                    "cracker_dispenser",
                    "aerosol_spray_paint",
                    "broad_tip_marker",
                    "etching_product",
                    "flipper_knife",
                    "karambit",
                    "neck_knife",
                    "boot_knife",
                    "bayonet",
                    "marketed_for_self_defense",
                    "air_gun_pistol_grip",
                    "emissions_part_no_carb_eo",
                    "emissions_defeat_device",
                    "gas_small_offroad_engine",
                    "portable_generator_gas",
                    "voc_noncompliant_consumer_product",
                    "catalytic_converter",
                    "used_catalytic_converter",
                    "sunscreen",
                    "oxybenzone",
                    "octinoxate",
                    "avobenzone",
                    "octocrylene",
                    "non_mineral_sunscreen",
                    "aminobenzoic_acid",
                    "trolamine_salicylate",
                    "no_fda_marketing_order",
                    "box_cutter",
                    "pfas_intentionally_added",
                    "pfas_cookware",
                    "pfas_textile_apparel",
                    "pfas_outdoor_apparel",
                    "pfas_intimate_apparel",
                    "pfas_textile_furnishing",
                    "pfas_upholstered_furniture",
                    "pfas_juvenile_product",
                    "pfas_carpet_rug",
                    "pfas_fabric_treatment",
                    "pfas_ski_wax",
                    "pfas_dental_floss",
                    "pfas_menstrual_product",
                    "pfas_incontinence_product",
                    "pfas_cleaning_product",
                    "pfas_food_packaging",
                    "pfas_artificial_turf",
                    "cider"
                  ]
                }
              },
              "flagsAll": {
                "type": "array",
                "items": {
                  "enum": [
                    "ballistic_knife",
                    "metal_knuckle",
                    "knuckle_knife",
                    "throwing_star",
                    "cane_sword",
                    "belt_buckle",
                    "lipstick_case_knife",
                    "writing_pen_knife",
                    "air_gauge_knife",
                    "undetectable",
                    "bowie",
                    "blackjack",
                    "slungshot",
                    "sand_club",
                    "nunchaku",
                    "locked_draw_case",
                    "spray_over_0_75_oz",
                    "net_weight_over_2_5_oz",
                    "not_pocket_sized",
                    "not_personal_protection_size",
                    "fogger_area_dispersal",
                    "projectile",
                    "non_aerosol",
                    "contains_tear_gas_cn",
                    "contains_tear_gas_cs",
                    "unauthorized_compound",
                    "lacks_ca_tear_gas_label",
                    "no_serial_number",
                    "no_use_instructions",
                    "no_expiration_date",
                    "ammunition",
                    "handgun_ammunition",
                    "ammo_components",
                    "armor_piercing_ammunition",
                    "explosive_incendiary_ammunition",
                    "teflon_coated_bullet",
                    "dragons_breath_shell",
                    "flechette_or_bolo_shell",
                    "magazine_over_10",
                    "magazine_over_15",
                    "magazine_over_17",
                    "handgun_magazine",
                    "long_gun_magazine",
                    "magazine_parts_kit",
                    "shotgun_ammunition",
                    "shotgun_magazine_extension",
                    "baton",
                    "sap_glove",
                    "kubotan",
                    "sword",
                    "oc_over_18_percent",
                    "contains_tear_gas_cs_aerosol",
                    "tear_gas_over_2_percent",
                    "no_manufacturer_name",
                    "non_metal_knuckle",
                    "air_gun",
                    "airsoft",
                    "paintball_marker",
                    "imitation_firearm",
                    "realistic_appearance",
                    "lacks_federal_orange_marking",
                    "lacks_ca_airsoft_fluorescent_markings",
                    "caliber_over_177",
                    "muzzle_velocity_700fps_plus",
                    "muzzle_velocity_400fps_plus",
                    "concealable_air_gun",
                    "body_armor",
                    "crossbow",
                    "consumer_fireworks",
                    "aerial_fireworks",
                    "sparklers_novelties",
                    "wire_sparklers",
                    "banned_audible_fireworks",
                    "laser_pointer",
                    "laser_over_5mw",
                    "wine",
                    "beer",
                    "spirits",
                    "alcohol_from_producer",
                    "alcohol_from_retailer",
                    "firearm",
                    "handgun",
                    "long_gun",
                    "semiauto_rifle",
                    "semiauto_detachable_magazine",
                    "assault_weapon",
                    "assault_weapon_attachment",
                    "unfinished_frame_receiver",
                    "frame_receiver_jig",
                    "weapon_parts_kit",
                    "firearm_3d_print_file",
                    "firearm_manufacturing_machine",
                    "firearm_barrel",
                    "suppressor",
                    "suppressor_part",
                    "solvent_trap",
                    "rapid_fire_device",
                    "binary_trigger",
                    "forced_reset_trigger",
                    "machinegun_conversion_device",
                    "pistol_brace",
                    "convertible_pistol",
                    "vape",
                    "contains_nicotine",
                    "cigarettes",
                    "roll_your_own",
                    "cigars",
                    "pipe_tobacco",
                    "smokeless_tobacco",
                    "nicotine_pouch",
                    "flavored",
                    "menthol",
                    "flavor_not_menthol",
                    "not_on_state_directory",
                    "on_state_prohibited_list",
                    "no_fda_pmta_status",
                    "foreign_adversary_origin",
                    "youth_appealing_design",
                    "contains_other_psychoactive",
                    "nicotine_analogue",
                    "nicotine_over_35_mg_ml",
                    "nicotine_over_75_mg_ml",
                    "hemp_intoxicating",
                    "hemp_delta9_edible",
                    "cbd_product",
                    "smokable_hemp",
                    "thca_flower",
                    "cbd_food_or_beverage",
                    "hemp_synthetic_cannabinoid",
                    "hemp_converted_cannabinoid",
                    "hemp_thc_beverage",
                    "hemp_vape",
                    "hemp_preroll",
                    "hemp_flower",
                    "hemp_topical",
                    "cbd_full_spectrum",
                    "cbd_thc_free",
                    "kratom",
                    "seven_oh_mitragynine",
                    "mitragynine_pseudoindoxyl",
                    "kratom_extract",
                    "kratom_inhalable",
                    "kratom_vape",
                    "kratom_food_or_beverage",
                    "kratom_confection",
                    "kratom_synthetic_alkaloid",
                    "lithium_battery_loose",
                    "lithium_battery_in_equipment",
                    "power_bank",
                    "lithium_battery_over_100wh",
                    "flammable_aerosol",
                    "flammable_liquid_cosmetic",
                    "flammable_liquid_low_flashpoint",
                    "matches",
                    "strike_anywhere_matches",
                    "lighter",
                    "butane_refill",
                    "dry_ice",
                    "amanita_muscaria",
                    "amanita_conventional_food",
                    "psilocybin_spores",
                    "salvia_divinorum",
                    "salvia_extract",
                    "blue_lotus",
                    "kanna",
                    "dietary_supplement",
                    "weight_loss_supplement",
                    "muscle_building_supplement",
                    "tianeptine",
                    "phenibut",
                    "dmaa_or_dmha",
                    "ephedra",
                    "pure_powdered_caffeine",
                    "kava",
                    "nitrous_oxide_charger",
                    "nitrous_oxide_tank",
                    "flavored_nitrous_oxide",
                    "cracker_dispenser",
                    "aerosol_spray_paint",
                    "broad_tip_marker",
                    "etching_product",
                    "flipper_knife",
                    "karambit",
                    "neck_knife",
                    "boot_knife",
                    "bayonet",
                    "marketed_for_self_defense",
                    "air_gun_pistol_grip",
                    "emissions_part_no_carb_eo",
                    "emissions_defeat_device",
                    "gas_small_offroad_engine",
                    "portable_generator_gas",
                    "voc_noncompliant_consumer_product",
                    "catalytic_converter",
                    "used_catalytic_converter",
                    "sunscreen",
                    "oxybenzone",
                    "octinoxate",
                    "avobenzone",
                    "octocrylene",
                    "non_mineral_sunscreen",
                    "aminobenzoic_acid",
                    "trolamine_salicylate",
                    "no_fda_marketing_order",
                    "box_cutter",
                    "pfas_intentionally_added",
                    "pfas_cookware",
                    "pfas_textile_apparel",
                    "pfas_outdoor_apparel",
                    "pfas_intimate_apparel",
                    "pfas_textile_furnishing",
                    "pfas_upholstered_furniture",
                    "pfas_juvenile_product",
                    "pfas_carpet_rug",
                    "pfas_fabric_treatment",
                    "pfas_ski_wax",
                    "pfas_dental_floss",
                    "pfas_menstrual_product",
                    "pfas_incontinence_product",
                    "pfas_cleaning_product",
                    "pfas_food_packaging",
                    "pfas_artificial_turf",
                    "cider"
                  ]
                }
              },
              "bladeLengthOverIn": {
                "type": "number"
              },
              "bladeLengthAtLeastIn": {
                "type": "number"
              },
              "sprayOzOver": {
                "type": "number"
              },
              "sprayOzAtLeast": {
                "type": "number"
              }
            }
          },
          "states": {
            "oneOf": [
              {
                "const": "all"
              },
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "example": "NY"
                }
              }
            ]
          },
          "zipPrefixes": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "string",
              "pattern": "^\\d{3,5}$"
            }
          },
          "effect": {
            "enum": [
              "block",
              "age16",
              "age18",
              "age19",
              "age21"
            ]
          }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "includeDrafts": {
            "type": "boolean",
            "description": "Default true; false for reviewed rules only"
          },
          "storeRules": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/StoreRule"
            },
            "description": "Applied to every item"
          },
          "items": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "object",
              "required": [
                "category"
              ],
              "description": "zip or state is required. Product fields as in Product; mechanism defaults to none.",
              "properties": {
                "id": {
                  "type": [
                    "string",
                    "number"
                  ]
                },
                "zip": {
                  "type": "string",
                  "pattern": "^\\d{5}$"
                },
                "state": {
                  "type": "string",
                  "example": "GA"
                },
                "category": {
                  "enum": [
                    "folding_knife",
                    "fixed_blade",
                    "balisong",
                    "pepper_spray",
                    "stun_gun",
                    "other"
                  ]
                },
                "mechanism": {
                  "enum": [
                    "manual",
                    "assisted",
                    "automatic",
                    "otf",
                    "gravity",
                    "fixed",
                    "none"
                  ]
                },
                "bladeLengthIn": {
                  "type": "number"
                },
                "sprayOz": {
                  "type": "number"
                },
                "edge": {
                  "enum": [
                    "single",
                    "double",
                    "none"
                  ]
                },
                "style": {
                  "enum": [
                    "standard",
                    "dagger",
                    "dirk",
                    "stiletto",
                    "throwing",
                    "none"
                  ]
                },
                "flags": {
                  "type": "array",
                  "items": {
                    "enum": [
                      "ballistic_knife",
                      "metal_knuckle",
                      "knuckle_knife",
                      "throwing_star",
                      "cane_sword",
                      "belt_buckle",
                      "lipstick_case_knife",
                      "writing_pen_knife",
                      "air_gauge_knife",
                      "undetectable",
                      "bowie",
                      "blackjack",
                      "slungshot",
                      "sand_club",
                      "nunchaku",
                      "locked_draw_case",
                      "spray_over_0_75_oz",
                      "net_weight_over_2_5_oz",
                      "not_pocket_sized",
                      "not_personal_protection_size",
                      "fogger_area_dispersal",
                      "projectile",
                      "non_aerosol",
                      "contains_tear_gas_cn",
                      "contains_tear_gas_cs",
                      "unauthorized_compound",
                      "lacks_ca_tear_gas_label",
                      "no_serial_number",
                      "no_use_instructions",
                      "no_expiration_date",
                      "ammunition",
                      "handgun_ammunition",
                      "ammo_components",
                      "armor_piercing_ammunition",
                      "explosive_incendiary_ammunition",
                      "teflon_coated_bullet",
                      "dragons_breath_shell",
                      "flechette_or_bolo_shell",
                      "magazine_over_10",
                      "magazine_over_15",
                      "magazine_over_17",
                      "handgun_magazine",
                      "long_gun_magazine",
                      "magazine_parts_kit",
                      "shotgun_ammunition",
                      "shotgun_magazine_extension",
                      "baton",
                      "sap_glove",
                      "kubotan",
                      "sword",
                      "oc_over_18_percent",
                      "contains_tear_gas_cs_aerosol",
                      "tear_gas_over_2_percent",
                      "no_manufacturer_name",
                      "non_metal_knuckle",
                      "air_gun",
                      "airsoft",
                      "paintball_marker",
                      "imitation_firearm",
                      "realistic_appearance",
                      "lacks_federal_orange_marking",
                      "lacks_ca_airsoft_fluorescent_markings",
                      "caliber_over_177",
                      "muzzle_velocity_700fps_plus",
                      "muzzle_velocity_400fps_plus",
                      "concealable_air_gun",
                      "body_armor",
                      "crossbow",
                      "consumer_fireworks",
                      "aerial_fireworks",
                      "sparklers_novelties",
                      "wire_sparklers",
                      "banned_audible_fireworks",
                      "laser_pointer",
                      "laser_over_5mw",
                      "wine",
                      "beer",
                      "spirits",
                      "alcohol_from_producer",
                      "alcohol_from_retailer",
                      "firearm",
                      "handgun",
                      "long_gun",
                      "semiauto_rifle",
                      "semiauto_detachable_magazine",
                      "assault_weapon",
                      "assault_weapon_attachment",
                      "unfinished_frame_receiver",
                      "frame_receiver_jig",
                      "weapon_parts_kit",
                      "firearm_3d_print_file",
                      "firearm_manufacturing_machine",
                      "firearm_barrel",
                      "suppressor",
                      "suppressor_part",
                      "solvent_trap",
                      "rapid_fire_device",
                      "binary_trigger",
                      "forced_reset_trigger",
                      "machinegun_conversion_device",
                      "pistol_brace",
                      "convertible_pistol",
                      "vape",
                      "contains_nicotine",
                      "cigarettes",
                      "roll_your_own",
                      "cigars",
                      "pipe_tobacco",
                      "smokeless_tobacco",
                      "nicotine_pouch",
                      "flavored",
                      "menthol",
                      "flavor_not_menthol",
                      "not_on_state_directory",
                      "on_state_prohibited_list",
                      "no_fda_pmta_status",
                      "foreign_adversary_origin",
                      "youth_appealing_design",
                      "contains_other_psychoactive",
                      "nicotine_analogue",
                      "nicotine_over_35_mg_ml",
                      "nicotine_over_75_mg_ml",
                      "hemp_intoxicating",
                      "hemp_delta9_edible",
                      "cbd_product",
                      "smokable_hemp",
                      "thca_flower",
                      "cbd_food_or_beverage",
                      "hemp_synthetic_cannabinoid",
                      "hemp_converted_cannabinoid",
                      "hemp_thc_beverage",
                      "hemp_vape",
                      "hemp_preroll",
                      "hemp_flower",
                      "hemp_topical",
                      "cbd_full_spectrum",
                      "cbd_thc_free",
                      "kratom",
                      "seven_oh_mitragynine",
                      "mitragynine_pseudoindoxyl",
                      "kratom_extract",
                      "kratom_inhalable",
                      "kratom_vape",
                      "kratom_food_or_beverage",
                      "kratom_confection",
                      "kratom_synthetic_alkaloid",
                      "lithium_battery_loose",
                      "lithium_battery_in_equipment",
                      "power_bank",
                      "lithium_battery_over_100wh",
                      "flammable_aerosol",
                      "flammable_liquid_cosmetic",
                      "flammable_liquid_low_flashpoint",
                      "matches",
                      "strike_anywhere_matches",
                      "lighter",
                      "butane_refill",
                      "dry_ice",
                      "amanita_muscaria",
                      "amanita_conventional_food",
                      "psilocybin_spores",
                      "salvia_divinorum",
                      "salvia_extract",
                      "blue_lotus",
                      "kanna",
                      "dietary_supplement",
                      "weight_loss_supplement",
                      "muscle_building_supplement",
                      "tianeptine",
                      "phenibut",
                      "dmaa_or_dmha",
                      "ephedra",
                      "pure_powdered_caffeine",
                      "kava",
                      "nitrous_oxide_charger",
                      "nitrous_oxide_tank",
                      "flavored_nitrous_oxide",
                      "cracker_dispenser",
                      "aerosol_spray_paint",
                      "broad_tip_marker",
                      "etching_product",
                      "flipper_knife",
                      "karambit",
                      "neck_knife",
                      "boot_knife",
                      "bayonet",
                      "marketed_for_self_defense",
                      "air_gun_pistol_grip",
                      "emissions_part_no_carb_eo",
                      "emissions_defeat_device",
                      "gas_small_offroad_engine",
                      "portable_generator_gas",
                      "voc_noncompliant_consumer_product",
                      "catalytic_converter",
                      "used_catalytic_converter",
                      "sunscreen",
                      "oxybenzone",
                      "octinoxate",
                      "avobenzone",
                      "octocrylene",
                      "non_mineral_sunscreen",
                      "aminobenzoic_acid",
                      "trolamine_salicylate",
                      "no_fda_marketing_order",
                      "box_cutter",
                      "pfas_intentionally_added",
                      "pfas_cookware",
                      "pfas_textile_apparel",
                      "pfas_outdoor_apparel",
                      "pfas_intimate_apparel",
                      "pfas_textile_furnishing",
                      "pfas_upholstered_furniture",
                      "pfas_juvenile_product",
                      "pfas_carpet_rug",
                      "pfas_fabric_treatment",
                      "pfas_ski_wax",
                      "pfas_dental_floss",
                      "pfas_menstrual_product",
                      "pfas_incontinence_product",
                      "pfas_cleaning_product",
                      "pfas_food_packaging",
                      "pfas_artificial_turf",
                      "cider"
                    ]
                  }
                },
                "origin": {
                  "type": "string",
                  "description": "Ship-from state"
                },
                "carrier": {
                  "oneOf": [
                    {
                      "enum": [
                        "usps",
                        "ups",
                        "fedex",
                        "dhl",
                        "other"
                      ]
                    },
                    {
                      "type": "array",
                      "items": {
                        "enum": [
                          "usps",
                          "ups",
                          "fedex",
                          "dhl",
                          "other"
                        ]
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "BatchResponse": {
        "type": "object",
        "properties": {
          "rulesetVersion": {
            "type": "integer"
          },
          "rulesAsOf": {
            "type": "string"
          },
          "basis": {
            "enum": [
              "verified",
              "verified+drafts"
            ]
          },
          "results": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/CheckResult"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": [
                            "string",
                            "number",
                            "null"
                          ]
                        },
                        "state": {
                          "type": "string"
                        },
                        "zip": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  ]
                },
                {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "id": {
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "MatrixRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "object",
              "description": "productType, attributes, or both (as in /v1/check)",
              "properties": {
                "ref": {
                  "type": [
                    "string",
                    "number"
                  ]
                },
                "productType": {
                  "type": "string"
                },
                "attributes": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "originState": {
            "type": "string",
            "example": "TX"
          },
          "carriers": {
            "type": "array",
            "items": {
              "enum": [
                "usps",
                "ups",
                "fedex",
                "dhl",
                "other"
              ]
            }
          },
          "licenses": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "includeDrafts": {
            "type": "boolean",
            "description": "Default true; false for reviewed rules only"
          },
          "storeRules": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/StoreRule"
            },
            "description": "ZIP-prefix store rules come back as city rows"
          }
        }
      },
      "MatrixCell": {
        "type": "object",
        "properties": {
          "decision": {
            "enum": [
              "allow",
              "block",
              "age_verify"
            ]
          },
          "minimumAge": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ship": {
            "type": "boolean",
            "description": "true for a block caused only by carrier rules: ship with a carrier not in avoidCarriers (send carriers for an exact decision)"
          },
          "avoidCarriers": {
            "type": "array",
            "items": {
              "enum": [
                "usps",
                "ups",
                "fedex",
                "dhl",
                "other"
              ]
            },
            "description": "Omitted when none"
          },
          "licensesNeeded": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "License ids that would lift a LICENSE_REQUIRED block; omitted when none"
          },
          "codes": {
            "type": "array",
            "items": {
              "enum": [
                "PLATFORM_POLICY",
                "CARRIER_RESTRICTED",
                "BLOCKED_INTERSTATE",
                "BLOCKED_SPRAY_SIZE",
                "BLOCKED_AUTOMATIC_KNIFE",
                "BLOCKED_GRAVITY_KNIFE",
                "BLOCKED_ASSISTED_KNIFE",
                "BLOCKED_BLADE_LENGTH",
                "BLOCKED_BALLISTIC_KNIFE",
                "BLOCKED_KNUCKLES",
                "BLOCKED_DISGUISED_KNIFE",
                "BLOCKED_THROWING_STAR",
                "BLOCKED_SPRAY_FORMULA",
                "BLOCKED_SPRAY_LABELING",
                "BLOCKED_SPRAY_TYPE",
                "BLOCKED_BALISONG",
                "BLOCKED_PEPPER_SPRAY",
                "BLOCKED_STUN_GUN",
                "BLOCKED_BLADE_STYLE",
                "BLOCKED_PROHIBITED_ITEM",
                "BLOCKED",
                "AGE_16",
                "AGE_18",
                "AGE_19",
                "AGE_21",
                "LICENSE_REQUIRED",
                "STORE_POLICY"
              ]
            }
          },
          "coverage": {
            "type": [
              "string",
              "null"
            ],
            "description": "restricted / no_restriction_found / not_checked / unknown for the product's topic; not_checked means allow is not clearance"
          },
          "basis": {
            "$ref": "#/components/schemas/Basis"
          },
          "adjustedBy": {
            "type": "string",
            "description": "Set when your own rule feedback changed this cell"
          },
          "original": {
            "$ref": "#/components/schemas/Original"
          }
        }
      },
      "MatrixResponse": {
        "type": "object",
        "properties": {
          "rulesetVersion": {
            "type": "integer"
          },
          "rulesAsOf": {
            "type": "string"
          },
          "basis": {
            "enum": [
              "verified",
              "verified+drafts"
            ]
          },
          "states": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The 50 states and DC"
          },
          "cities": {
            "type": "array",
            "description": "Every ZIP-level jurisdiction checked",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "state": {
                  "type": "string"
                },
                "zipPrefixes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "results": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "ref": {
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "cells": {
                      "type": "object",
                      "additionalProperties": {
                        "$ref": "#/components/schemas/MatrixCell"
                      },
                      "description": "Keyed by two-letter state; state and federal law only"
                    },
                    "cities": {
                      "type": "array",
                      "description": "Cities whose answer differs from their state's cell; ZIPs starting with zipPrefixes get this answer",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/MatrixCell"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "state": {
                                "type": "string"
                              },
                              "zipPrefixes": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                },
                {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "ref": {
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "IngredientsResponse": {
        "type": "object",
        "properties": {
          "asOf": {
            "type": "string",
            "format": "date"
          },
          "jurisdiction": {
            "type": [
              "string",
              "null"
            ]
          },
          "researched": {
            "type": "boolean"
          },
          "ingredientCount": {
            "type": "integer"
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ingredient": {
                  "type": "string"
                },
                "jurisdiction": {
                  "type": "string"
                },
                "effect": {
                  "enum": [
                    "sale_ban",
                    "manufacture_ban",
                    "label",
                    "report",
                    "notice"
                  ]
                },
                "effectiveDate": {
                  "type": "string",
                  "format": "date"
                },
                "timing": {
                  "enum": [
                    "in_force",
                    "upcoming"
                  ]
                },
                "matchedBy": {
                  "enum": [
                    "cas",
                    "name",
                    "compound",
                    "class",
                    "pfas_heuristic"
                  ]
                },
                "threshold": {
                  "type": "string"
                },
                "ruleId": {
                  "type": "string"
                },
                "status": {
                  "enum": [
                    "draft",
                    "verified"
                  ]
                },
                "summary": {
                  "type": "string"
                },
                "citation": {
                  "type": "string"
                },
                "sourceUrl": {
                  "type": "string",
                  "format": "uri"
                },
                "lawText": {
                  "type": "string",
                  "description": "Verbatim statute text"
                }
              }
            }
          }
        }
      },
      "Law": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "jurisdiction": {
            "type": "string"
          },
          "citation": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri"
          },
          "retrievedAt": {
            "type": "string",
            "format": "date"
          },
          "scope": {
            "type": "array",
            "items": {
              "enum": [
                "sale",
                "transfer",
                "possession",
                "carry",
                "manufacture",
                "shipping"
              ]
            }
          },
          "lawText": {
            "type": "string",
            "description": "Verbatim text copied from sourceUrl"
          },
          "ruleIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PurchaseCap": {
        "type": "object",
        "required": [
          "quantity",
          "unit",
          "period",
          "per"
        ],
        "properties": {
          "quantity": {
            "type": "number"
          },
          "unit": {
            "enum": [
              "items",
              "bottles",
              "cases_9l",
              "liters",
              "gallons",
              "fl_oz",
              "grams",
              "ounces"
            ]
          },
          "period": {
            "enum": [
              "order",
              "day",
              "month",
              "quarter",
              "year"
            ]
          },
          "per": {
            "enum": [
              "buyer",
              "buyer_address"
            ]
          },
          "window": {
            "enum": [
              "calendar",
              "rolling"
            ],
            "description": "calendar (default): the UTC calendar day/month/quarter/year of the sale; rolling: the preceding 24 hours or 1/3/12 months"
          },
          "months": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "description": "With period month: a window of this many months (\"any two-month period\" = rolling, 2). Calendar windows of N months start in January."
          },
          "appliesTo": {
            "type": "object",
            "description": "The cap covers only these products of its rule (every list given must match), e.g. a wine-only cap on a wine-and-beer rule. Other products neither get this cap nor count toward it.",
            "properties": {
              "productTypes": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Product type ids (GET /v1/product-types)"
              },
              "flagsAny": {
                "type": "array",
                "items": {
                  "enum": [
                    "ballistic_knife",
                    "metal_knuckle",
                    "knuckle_knife",
                    "throwing_star",
                    "cane_sword",
                    "belt_buckle",
                    "lipstick_case_knife",
                    "writing_pen_knife",
                    "air_gauge_knife",
                    "undetectable",
                    "bowie",
                    "blackjack",
                    "slungshot",
                    "sand_club",
                    "nunchaku",
                    "locked_draw_case",
                    "spray_over_0_75_oz",
                    "net_weight_over_2_5_oz",
                    "not_pocket_sized",
                    "not_personal_protection_size",
                    "fogger_area_dispersal",
                    "projectile",
                    "non_aerosol",
                    "contains_tear_gas_cn",
                    "contains_tear_gas_cs",
                    "unauthorized_compound",
                    "lacks_ca_tear_gas_label",
                    "no_serial_number",
                    "no_use_instructions",
                    "no_expiration_date",
                    "ammunition",
                    "handgun_ammunition",
                    "ammo_components",
                    "armor_piercing_ammunition",
                    "explosive_incendiary_ammunition",
                    "teflon_coated_bullet",
                    "dragons_breath_shell",
                    "flechette_or_bolo_shell",
                    "magazine_over_10",
                    "magazine_over_15",
                    "magazine_over_17",
                    "handgun_magazine",
                    "long_gun_magazine",
                    "magazine_parts_kit",
                    "shotgun_ammunition",
                    "shotgun_magazine_extension",
                    "baton",
                    "sap_glove",
                    "kubotan",
                    "sword",
                    "oc_over_18_percent",
                    "contains_tear_gas_cs_aerosol",
                    "tear_gas_over_2_percent",
                    "no_manufacturer_name",
                    "non_metal_knuckle",
                    "air_gun",
                    "airsoft",
                    "paintball_marker",
                    "imitation_firearm",
                    "realistic_appearance",
                    "lacks_federal_orange_marking",
                    "lacks_ca_airsoft_fluorescent_markings",
                    "caliber_over_177",
                    "muzzle_velocity_700fps_plus",
                    "muzzle_velocity_400fps_plus",
                    "concealable_air_gun",
                    "body_armor",
                    "crossbow",
                    "consumer_fireworks",
                    "aerial_fireworks",
                    "sparklers_novelties",
                    "wire_sparklers",
                    "banned_audible_fireworks",
                    "laser_pointer",
                    "laser_over_5mw",
                    "wine",
                    "beer",
                    "spirits",
                    "alcohol_from_producer",
                    "alcohol_from_retailer",
                    "firearm",
                    "handgun",
                    "long_gun",
                    "semiauto_rifle",
                    "semiauto_detachable_magazine",
                    "assault_weapon",
                    "assault_weapon_attachment",
                    "unfinished_frame_receiver",
                    "frame_receiver_jig",
                    "weapon_parts_kit",
                    "firearm_3d_print_file",
                    "firearm_manufacturing_machine",
                    "firearm_barrel",
                    "suppressor",
                    "suppressor_part",
                    "solvent_trap",
                    "rapid_fire_device",
                    "binary_trigger",
                    "forced_reset_trigger",
                    "machinegun_conversion_device",
                    "pistol_brace",
                    "convertible_pistol",
                    "vape",
                    "contains_nicotine",
                    "cigarettes",
                    "roll_your_own",
                    "cigars",
                    "pipe_tobacco",
                    "smokeless_tobacco",
                    "nicotine_pouch",
                    "flavored",
                    "menthol",
                    "flavor_not_menthol",
                    "not_on_state_directory",
                    "on_state_prohibited_list",
                    "no_fda_pmta_status",
                    "foreign_adversary_origin",
                    "youth_appealing_design",
                    "contains_other_psychoactive",
                    "nicotine_analogue",
                    "nicotine_over_35_mg_ml",
                    "nicotine_over_75_mg_ml",
                    "hemp_intoxicating",
                    "hemp_delta9_edible",
                    "cbd_product",
                    "smokable_hemp",
                    "thca_flower",
                    "cbd_food_or_beverage",
                    "hemp_synthetic_cannabinoid",
                    "hemp_converted_cannabinoid",
                    "hemp_thc_beverage",
                    "hemp_vape",
                    "hemp_preroll",
                    "hemp_flower",
                    "hemp_topical",
                    "cbd_full_spectrum",
                    "cbd_thc_free",
                    "kratom",
                    "seven_oh_mitragynine",
                    "mitragynine_pseudoindoxyl",
                    "kratom_extract",
                    "kratom_inhalable",
                    "kratom_vape",
                    "kratom_food_or_beverage",
                    "kratom_confection",
                    "kratom_synthetic_alkaloid",
                    "lithium_battery_loose",
                    "lithium_battery_in_equipment",
                    "power_bank",
                    "lithium_battery_over_100wh",
                    "flammable_aerosol",
                    "flammable_liquid_cosmetic",
                    "flammable_liquid_low_flashpoint",
                    "matches",
                    "strike_anywhere_matches",
                    "lighter",
                    "butane_refill",
                    "dry_ice",
                    "amanita_muscaria",
                    "amanita_conventional_food",
                    "psilocybin_spores",
                    "salvia_divinorum",
                    "salvia_extract",
                    "blue_lotus",
                    "kanna",
                    "dietary_supplement",
                    "weight_loss_supplement",
                    "muscle_building_supplement",
                    "tianeptine",
                    "phenibut",
                    "dmaa_or_dmha",
                    "ephedra",
                    "pure_powdered_caffeine",
                    "kava",
                    "nitrous_oxide_charger",
                    "nitrous_oxide_tank",
                    "flavored_nitrous_oxide",
                    "cracker_dispenser",
                    "aerosol_spray_paint",
                    "broad_tip_marker",
                    "etching_product",
                    "flipper_knife",
                    "karambit",
                    "neck_knife",
                    "boot_knife",
                    "bayonet",
                    "marketed_for_self_defense",
                    "air_gun_pistol_grip",
                    "emissions_part_no_carb_eo",
                    "emissions_defeat_device",
                    "gas_small_offroad_engine",
                    "portable_generator_gas",
                    "voc_noncompliant_consumer_product",
                    "catalytic_converter",
                    "used_catalytic_converter",
                    "sunscreen",
                    "oxybenzone",
                    "octinoxate",
                    "avobenzone",
                    "octocrylene",
                    "non_mineral_sunscreen",
                    "aminobenzoic_acid",
                    "trolamine_salicylate",
                    "no_fda_marketing_order",
                    "box_cutter",
                    "pfas_intentionally_added",
                    "pfas_cookware",
                    "pfas_textile_apparel",
                    "pfas_outdoor_apparel",
                    "pfas_intimate_apparel",
                    "pfas_textile_furnishing",
                    "pfas_upholstered_furniture",
                    "pfas_juvenile_product",
                    "pfas_carpet_rug",
                    "pfas_fabric_treatment",
                    "pfas_ski_wax",
                    "pfas_dental_floss",
                    "pfas_menstrual_product",
                    "pfas_incontinence_product",
                    "pfas_cleaning_product",
                    "pfas_food_packaging",
                    "pfas_artificial_turf",
                    "cider"
                  ]
                }
              },
              "flagsNone": {
                "type": "array",
                "items": {
                  "enum": [
                    "ballistic_knife",
                    "metal_knuckle",
                    "knuckle_knife",
                    "throwing_star",
                    "cane_sword",
                    "belt_buckle",
                    "lipstick_case_knife",
                    "writing_pen_knife",
                    "air_gauge_knife",
                    "undetectable",
                    "bowie",
                    "blackjack",
                    "slungshot",
                    "sand_club",
                    "nunchaku",
                    "locked_draw_case",
                    "spray_over_0_75_oz",
                    "net_weight_over_2_5_oz",
                    "not_pocket_sized",
                    "not_personal_protection_size",
                    "fogger_area_dispersal",
                    "projectile",
                    "non_aerosol",
                    "contains_tear_gas_cn",
                    "contains_tear_gas_cs",
                    "unauthorized_compound",
                    "lacks_ca_tear_gas_label",
                    "no_serial_number",
                    "no_use_instructions",
                    "no_expiration_date",
                    "ammunition",
                    "handgun_ammunition",
                    "ammo_components",
                    "armor_piercing_ammunition",
                    "explosive_incendiary_ammunition",
                    "teflon_coated_bullet",
                    "dragons_breath_shell",
                    "flechette_or_bolo_shell",
                    "magazine_over_10",
                    "magazine_over_15",
                    "magazine_over_17",
                    "handgun_magazine",
                    "long_gun_magazine",
                    "magazine_parts_kit",
                    "shotgun_ammunition",
                    "shotgun_magazine_extension",
                    "baton",
                    "sap_glove",
                    "kubotan",
                    "sword",
                    "oc_over_18_percent",
                    "contains_tear_gas_cs_aerosol",
                    "tear_gas_over_2_percent",
                    "no_manufacturer_name",
                    "non_metal_knuckle",
                    "air_gun",
                    "airsoft",
                    "paintball_marker",
                    "imitation_firearm",
                    "realistic_appearance",
                    "lacks_federal_orange_marking",
                    "lacks_ca_airsoft_fluorescent_markings",
                    "caliber_over_177",
                    "muzzle_velocity_700fps_plus",
                    "muzzle_velocity_400fps_plus",
                    "concealable_air_gun",
                    "body_armor",
                    "crossbow",
                    "consumer_fireworks",
                    "aerial_fireworks",
                    "sparklers_novelties",
                    "wire_sparklers",
                    "banned_audible_fireworks",
                    "laser_pointer",
                    "laser_over_5mw",
                    "wine",
                    "beer",
                    "spirits",
                    "alcohol_from_producer",
                    "alcohol_from_retailer",
                    "firearm",
                    "handgun",
                    "long_gun",
                    "semiauto_rifle",
                    "semiauto_detachable_magazine",
                    "assault_weapon",
                    "assault_weapon_attachment",
                    "unfinished_frame_receiver",
                    "frame_receiver_jig",
                    "weapon_parts_kit",
                    "firearm_3d_print_file",
                    "firearm_manufacturing_machine",
                    "firearm_barrel",
                    "suppressor",
                    "suppressor_part",
                    "solvent_trap",
                    "rapid_fire_device",
                    "binary_trigger",
                    "forced_reset_trigger",
                    "machinegun_conversion_device",
                    "pistol_brace",
                    "convertible_pistol",
                    "vape",
                    "contains_nicotine",
                    "cigarettes",
                    "roll_your_own",
                    "cigars",
                    "pipe_tobacco",
                    "smokeless_tobacco",
                    "nicotine_pouch",
                    "flavored",
                    "menthol",
                    "flavor_not_menthol",
                    "not_on_state_directory",
                    "on_state_prohibited_list",
                    "no_fda_pmta_status",
                    "foreign_adversary_origin",
                    "youth_appealing_design",
                    "contains_other_psychoactive",
                    "nicotine_analogue",
                    "nicotine_over_35_mg_ml",
                    "nicotine_over_75_mg_ml",
                    "hemp_intoxicating",
                    "hemp_delta9_edible",
                    "cbd_product",
                    "smokable_hemp",
                    "thca_flower",
                    "cbd_food_or_beverage",
                    "hemp_synthetic_cannabinoid",
                    "hemp_converted_cannabinoid",
                    "hemp_thc_beverage",
                    "hemp_vape",
                    "hemp_preroll",
                    "hemp_flower",
                    "hemp_topical",
                    "cbd_full_spectrum",
                    "cbd_thc_free",
                    "kratom",
                    "seven_oh_mitragynine",
                    "mitragynine_pseudoindoxyl",
                    "kratom_extract",
                    "kratom_inhalable",
                    "kratom_vape",
                    "kratom_food_or_beverage",
                    "kratom_confection",
                    "kratom_synthetic_alkaloid",
                    "lithium_battery_loose",
                    "lithium_battery_in_equipment",
                    "power_bank",
                    "lithium_battery_over_100wh",
                    "flammable_aerosol",
                    "flammable_liquid_cosmetic",
                    "flammable_liquid_low_flashpoint",
                    "matches",
                    "strike_anywhere_matches",
                    "lighter",
                    "butane_refill",
                    "dry_ice",
                    "amanita_muscaria",
                    "amanita_conventional_food",
                    "psilocybin_spores",
                    "salvia_divinorum",
                    "salvia_extract",
                    "blue_lotus",
                    "kanna",
                    "dietary_supplement",
                    "weight_loss_supplement",
                    "muscle_building_supplement",
                    "tianeptine",
                    "phenibut",
                    "dmaa_or_dmha",
                    "ephedra",
                    "pure_powdered_caffeine",
                    "kava",
                    "nitrous_oxide_charger",
                    "nitrous_oxide_tank",
                    "flavored_nitrous_oxide",
                    "cracker_dispenser",
                    "aerosol_spray_paint",
                    "broad_tip_marker",
                    "etching_product",
                    "flipper_knife",
                    "karambit",
                    "neck_knife",
                    "boot_knife",
                    "bayonet",
                    "marketed_for_self_defense",
                    "air_gun_pistol_grip",
                    "emissions_part_no_carb_eo",
                    "emissions_defeat_device",
                    "gas_small_offroad_engine",
                    "portable_generator_gas",
                    "voc_noncompliant_consumer_product",
                    "catalytic_converter",
                    "used_catalytic_converter",
                    "sunscreen",
                    "oxybenzone",
                    "octinoxate",
                    "avobenzone",
                    "octocrylene",
                    "non_mineral_sunscreen",
                    "aminobenzoic_acid",
                    "trolamine_salicylate",
                    "no_fda_marketing_order",
                    "box_cutter",
                    "pfas_intentionally_added",
                    "pfas_cookware",
                    "pfas_textile_apparel",
                    "pfas_outdoor_apparel",
                    "pfas_intimate_apparel",
                    "pfas_textile_furnishing",
                    "pfas_upholstered_furniture",
                    "pfas_juvenile_product",
                    "pfas_carpet_rug",
                    "pfas_fabric_treatment",
                    "pfas_ski_wax",
                    "pfas_dental_floss",
                    "pfas_menstrual_product",
                    "pfas_incontinence_product",
                    "pfas_cleaning_product",
                    "pfas_food_packaging",
                    "pfas_artificial_turf",
                    "cider"
                  ]
                },
                "description": "The product carries none of these flags (wine but not cider)"
              }
            }
          }
        }
      },
      "PurchaseRequest": {
        "type": "object",
        "required": [
          "buyer",
          "destination",
          "items"
        ],
        "properties": {
          "buyer": {
            "type": "string",
            "maxLength": 256,
            "description": "Your opaque customer id, or sha256 hex of the trimmed, lowercased email. Never the email itself."
          },
          "destination": {
            "type": "object",
            "required": [
              "country",
              "province"
            ],
            "properties": {
              "country": {
                "type": "string",
                "example": "US"
              },
              "province": {
                "type": "string",
                "example": "NY"
              },
              "zip": {
                "type": "string",
                "example": "10001"
              },
              "line1": {
                "type": "string",
                "description": "Optional street line; separates addresses for per-address (household) caps. Stored only as a salted hash."
              }
            }
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "quantity",
                "unit"
              ],
              "properties": {
                "ref": {
                  "type": "string"
                },
                "productType": {
                  "type": "string"
                },
                "attributes": {
                  "$ref": "#/components/schemas/Product"
                },
                "quantity": {
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "unit": {
                  "enum": [
                    "items",
                    "bottles",
                    "cases_9l",
                    "liters",
                    "gallons",
                    "fl_oz",
                    "grams",
                    "ounces"
                  ]
                },
                "measures": {
                  "type": "array",
                  "maxItems": 2,
                  "description": "The same line in other dimensions, e.g. quantity 2, unit bottles, measures [{quantity: 1.5, unit: liters}], so a bottle cap and a liter cap both count it. Each cap uses quantity + unit if it converts, else the first measure that does; CAP_UNIT_MISMATCH only when none does. One unit per dimension (count, volume, weight).",
                  "items": {
                    "type": "object",
                    "required": [
                      "quantity",
                      "unit"
                    ],
                    "properties": {
                      "quantity": {
                        "type": "number",
                        "exclusiveMinimum": 0
                      },
                      "unit": {
                        "enum": [
                          "items",
                          "bottles",
                          "cases_9l",
                          "liters",
                          "gallons",
                          "fl_oz",
                          "grams",
                          "ounces"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "includeDrafts": {
            "type": "boolean",
            "description": "Default true: caps on draft (unreviewed) rules apply too; false for reviewed rules only"
          }
        }
      },
      "PurchaseCapsResponse": {
        "type": "object",
        "properties": {
          "rulesetVersion": {
            "type": "integer"
          },
          "basis": {
            "enum": [
              "verified",
              "verified+drafts"
            ]
          },
          "ok": {
            "type": "boolean",
            "description": "Every item fits in every cap"
          },
          "priorOrders": {
            "type": "integer",
            "description": "Orders recorded for this buyer in the last 400 days"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ref": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "ok": {
                  "type": "boolean"
                },
                "basis": {
                  "$ref": "#/components/schemas/Basis"
                },
                "caps": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ruleId": {
                        "type": "string"
                      },
                      "capIndex": {
                        "type": "integer",
                        "description": "Which of the rule's caps (a rule may have several, e.g. 9 gallons a month and 36 gallons a year); ruleId + capIndex identifies a cap"
                      },
                      "ok": {
                        "type": "boolean"
                      },
                      "remaining": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "description": "What the buyer may still buy in this window, in cap.unit"
                      },
                      "used": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "requested": {
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "cap": {
                        "$ref": "#/components/schemas/PurchaseCap"
                      },
                      "windowStart": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "code": {
                        "enum": [
                          "OVER_PURCHASE_CAP",
                          "CAP_UNIT_MISMATCH",
                          null
                        ],
                        "description": "CAP_UNIT_MISMATCH: neither the item's unit nor any of its measures (or a recorded line's) converts to the cap's; send a volume, weight or count unit to match, or add it as a measure"
                      },
                      "summary": {
                        "type": "string"
                      },
                      "citation": {
                        "type": "string"
                      },
                      "sourceUrl": {
                        "type": "string",
                        "format": "uri"
                      },
                      "jurisdiction": {
                        "type": "string"
                      },
                      "status": {
                        "enum": [
                          "draft",
                          "verified"
                        ]
                      },
                      "basis": {
                        "$ref": "#/components/schemas/Basis"
                      },
                      "adjustedBy": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "LookupResult": {
        "type": "object",
        "properties": {
          "zip": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string"
          },
          "precision": {
            "enum": [
              "zip",
              "state"
            ]
          },
          "jurisdictions": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "verdict": {
            "type": [
              "object",
              "null"
            ],
            "description": "With a product: enforced (the answer: draft rules included unless includeDrafts=false), reviewedOnly (reviewed rules alone) and ifDraftsApproved (every draft applied; same as enforced by default). Each has decision, minimumAge, basis, ruleIds, licensesNeeded."
          },
          "rules": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A rule without its law text; basis says draft or reviewed, and adjustedBy marks one your own feedback changed"
            }
          },
          "disclaimer": {
            "type": "string"
          },
          "laws": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Law"
            }
          }
        }
      }
    }
  }
}