{
  "openapi": "3.1.0",
  "info": {
    "title": "HTS Calculator API",
    "version": "0.1.0",
    "summary": "US duty stacks, HTS lines and revisions, and IEEPA refund calculations, with citations.",
    "description": "Every response carries the dataset version and provenance. Values are copied by code from primary sources; where an AI judged something, the method and confidence are recorded.\n\nAuthentication: send your key in the `X-API-Key` header. Quotas are monthly units; most lookups cost 1 unit.\n\nPlans and prices: see the pricing page.\n\nReference data and calculations from HTS codes you supply. We do not classify goods; entry filings need a licensed customs broker.",
    "license": {
      "name": "Proprietary; data licences per source in meta.sources"
    }
  },
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "servers": [
    {
      "url": "https://api.htscalculator.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Duty Stack API",
      "description": "The base rate plus every Chapter 99 line for an HTS code, origin and entry date, with citations and the duty in dollars.",
      "x-product": "tariffs",
      "x-product-line": "duty-stack-api"
    },
    {
      "name": "HTS Lookup & History API",
      "description": "The tariff schedule as of any date: lines, base rates, revisions, changes and the Chapter 99 measures that reach a code.",
      "x-product": "tariffs",
      "x-product-line": "hts-lookup-api"
    },
    {
      "name": "IEEPA Refund API and Estimator",
      "description": "Entry lines in: the refundable IEEPA amount and the CAPE route for each line out.",
      "x-product": "tariffs",
      "x-product-line": "ieepa-refund-api"
    },
    {
      "name": "Tariff Change Feed",
      "description": "Every dated change to Chapter 99 measures, HTS lines and base rates, as a feed you can poll.",
      "x-product": "tariffs",
      "x-product-line": "change-feed"
    },
    {
      "name": "Account",
      "description": "Signup, account, keys, datasets and usage"
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol server for AI agents"
    },
    {
      "name": "Demo",
      "description": "Public, rate-limited demo of the sample requests shown on the sites, and the free duty calculator (no key, not metered)"
    }
  ],
  "paths": {
    "/v1/tariffs/duty-stack": {
      "post": {
        "operationId": "tariffs_duty_stack",
        "tags": [
          "Duty Stack API"
        ],
        "x-product": "tariffs",
        "x-product-line": "duty-stack-api",
        "summary": "Duty stack for an HTS code, origin and date",
        "description": "Base MFN rate plus every Chapter 99 line (Section 301, 232, IEEPA and others) that applies on the entry date (2025-01-01 to 2026-10-09), with the lines considered and not applied, totals, attributes the HTS code itself settles, and citations; with entered_value_usd, also the duty in dollars per line and in total (amounts). If a fact about the goods decides between lines and you did not declare it, the result branches on it. Reference calculation from the HTS code you supply: we do not classify goods.\n\nQuota cost: 10 units. MCP tool: `tariffs_duty_stack`.",
        "x-units": 10,
        "x-mcp-tool": "tariffs_duty_stack",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_duty_stack_body"
              },
              "example": {
                "hts10": "6112194050",
                "origin": "CN",
                "entry_date": "2025-12-07",
                "export_date": "2025-11-17",
                "mode": "vessel",
                "declared_attributes": {},
                "entered_value_usd": 48250
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body over 512 KB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Body is not application/json",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/duty-stack/batch": {
      "post": {
        "operationId": "tariffs_duty_stack_batch",
        "tags": [
          "Duty Stack API"
        ],
        "x-product": "tariffs",
        "x-product-line": "duty-stack-api",
        "summary": "Duty stacks for many lines",
        "description": "Up to 200 lines (HTS code, origin, entry date, optional value and declared facts) in one call; each line answers as POST /v1/tariffs/duty-stack does, or with its own error. The summary adds up the dollar totals that are numbers. Reference calculations from the codes you supply: we do not classify goods.\n\nQuota cost: 10 units per line. MCP tool: `tariffs_duty_stack_batch`.",
        "x-units": "10 units per line",
        "x-mcp-tool": "tariffs_duty_stack_batch",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_duty_stack_batch_body"
              },
              "example": {
                "lines": [
                  {
                    "line_id": "A1",
                    "hts10": "7318158066",
                    "origin": "CN",
                    "entry_date": "2025-08-20",
                    "entered_value_usd": 10000
                  },
                  {
                    "line_id": "A2",
                    "hts10": "8471300100",
                    "origin": "VN",
                    "entry_date": "2025-09-15",
                    "entered_value_usd": 120000
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body over 512 KB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Body is not application/json",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/compare-origins": {
      "post": {
        "operationId": "tariffs_compare_origins",
        "tags": [
          "Duty Stack API"
        ],
        "x-product": "tariffs",
        "x-product-line": "duty-stack-api",
        "summary": "Compare origins for one HTS code",
        "description": "One HTS code and entry date, up to 20 countries of origin: the total duty (and dollars with entered_value_usd), the Chapter 99 headings and branches for each, and the origins ranked lowest first where the total is a number.\n\nQuota cost: 10 units per distinct origin. MCP tool: `tariffs_compare_origins`.",
        "x-units": "10 units per distinct origin",
        "x-mcp-tool": "tariffs_compare_origins",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_compare_origins_body"
              },
              "example": {
                "hts10": "6112194050",
                "origins": [
                  "CN",
                  "VN",
                  "IN",
                  "MX",
                  "BD",
                  "DE"
                ],
                "entry_date": "2026-10-09",
                "entered_value_usd": 10000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body over 512 KB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Body is not application/json",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/hts/search": {
      "get": {
        "operationId": "tariffs_hts_search",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "Search the tariff schedule's text",
        "description": "Lines of the current HTS release whose text (with their parent lines) contains every word as a whole word (or its plural or singular: screw = screws). By default the lines whose own text matches the words best come first ('cap screws' finds the line 'Cap screws' before 'Machine screws ... (not including cap screws)'; each line has its score and why); order=schedule gives schedule order. For finding a line whose wording you know: it orders text matches only, does not choose a code for a product, and is not classification.\n\nQuota cost: 1 unit. MCP tool: `tariffs_hts_search`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_hts_search",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "cap screws"
          },
          {
            "name": "chapter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{2}$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "example": 5
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "relevance: how well the lines' text matches the words (the 500 lines with the most words in their own text are ranked); schedule: chapter, then line, through all matches",
            "schema": {
              "type": "string",
              "enum": [
                "relevance",
                "schedule"
              ],
              "default": "relevance"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/hts/{hts}": {
      "get": {
        "operationId": "tariffs_hts",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "HTS line lookup",
        "description": "An HTS line (10 digits) or every statistical line under a subheading (8 digits): description with its hierarchy and units (current release), the column 1 General rate in force on a date, current special and column 2 rates, and the HTS revision in force.\n\nQuota cost: 1 unit. MCP tool: `tariffs_hts_lookup`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_hts_lookup",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "hts",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{8,13}$"
            },
            "example": "6112194050"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2025-12-07"
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/hts/{hts}/history": {
      "get": {
        "operationId": "tariffs_hts_history",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "Revision history of an HTS line",
        "description": "Column 1 General rate intervals by HTS release (2025HTSBasic to the current release), and established/discontinued events from the Change Records.\n\nQuota cost: 1 unit. MCP tool: `tariffs_hts_history`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_hts_history",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "hts",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{10,13}$"
            },
            "example": "0901110035"
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/revisions": {
      "get": {
        "operationId": "tariffs_revisions",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "HTS revisions",
        "description": "HTS releases with their validity windows and links to the official PDF and Change Record.\n\nQuota cost: 1 unit. MCP tool: `tariffs_revisions`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_revisions",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2026-09-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/measures/{heading}": {
      "get": {
        "operationId": "tariffs_measure",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "A Chapter 99 measure",
        "description": "Every rule under a Chapter 99 heading, 9903 or 9904 (versions over time, country lists, quotas), or one rule by the rule_id GET /v1/tariffs/measures gives (the way to fetch rules without a heading, such as postal measures): authority, rate as published, valuation basis, countries, entry dates, scope size, conditions, stacking relations and citations with quotes.\n\nQuota cost: 1 unit. MCP tool: `tariffs_measure`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_measure",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "heading",
            "in": "path",
            "required": true,
            "description": "Chapter 99 heading (e.g. 9903.01.24, 9904.02.01) or a rule_id (e.g. OTH-122-POSTAL; encode / as %2F)",
            "schema": {
              "type": "string",
              "pattern": "^(99\\d{2}\\.\\d{2}\\.\\d{2}|[A-Za-z0-9][A-Za-z0-9_./-]{2,59})$"
            },
            "example": "9903.01.24"
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/measures": {
      "get": {
        "operationId": "tariffs_measures",
        "tags": [
          "HTS Lookup & History API"
        ],
        "x-product": "tariffs",
        "x-product-line": "hts-lookup-api",
        "summary": "Measures that reach an HTS code",
        "description": "Chapter 99 rules whose scope reaches an HTS code (listed by prefix, covering all goods except listed ones, or scoped by a description the code alone does not settle), optionally for one origin and entry date, newest first. Whether a measure applies to an entry is decided by the duty stack.\n\nQuota cost: 1 unit. MCP tool: `tariffs_measures_for_hts`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_measures_for_hts",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "hts",
            "in": "query",
            "required": true,
            "description": "HTS heading, subheading or line (4 to 10 digits)",
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{4,13}$"
            },
            "example": "7318158066"
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "example": "CN"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2025-08-20"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 10
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/changes": {
      "get": {
        "operationId": "tariffs_changes",
        "tags": [
          "Tariff Change Feed"
        ],
        "x-product": "tariffs",
        "x-product-line": "change-feed",
        "summary": "Tariff change feed",
        "description": "Dated changes in the dataset, newest first: Chapter 99 measures starting or ending (by entry date, with the first citation), HTS lines established, discontinued or modified (USITC Change Records), and column 1 General rate changes between releases. Filter by date range, kind and HTS code. Measures already in force on the first entry date the rules cover (2025-01-01) are counted (in_force_at_coverage_start), not listed as starting then.\n\nQuota cost: 1 unit. MCP tool: `tariffs_changes`.",
        "x-units": 1,
        "x-mcp-tool": "tariffs_changes",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "required": true,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2026-09-01"
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "measure",
                "hts_line",
                "base_rate"
              ]
            }
          },
          {
            "name": "hts",
            "in": "query",
            "required": false,
            "description": "Only changes reaching this heading, subheading or line; each measure event says how it reaches the code (scope_match: listed, all goods except listed codes, or a description the code alone does not settle)",
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{4,13}$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "example": 20
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tariffs/ieepa-refund": {
      "post": {
        "operationId": "tariffs_ieepa_refund",
        "tags": [
          "IEEPA Refund API and Estimator"
        ],
        "x-product": "tariffs",
        "x-product-line": "ieepa-refund-api",
        "summary": "IEEPA refund calculation for entry lines",
        "description": "For each entry line: the IEEPA percentage the duty stack applies on the entry date, the IEEPA duty on the entered value, the refundable amount (or the IEEPA duty actually paid, if you declare it), and the CAPE route (Phase 1, Phase 2, a later deployment, or outside CAPE) from liquidation and reconciliation status, with quotes from the CBP IEEPA Duty Refunds page. Interest is not computed. A reference calculation, not a CAPE declaration.\n\nQuota cost: 10 units per line. MCP tool: `tariffs_ieepa_refund`.",
        "x-units": "10 units per line",
        "x-mcp-tool": "tariffs_ieepa_refund",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_ieepa_refund_body"
              },
              "example": {
                "as_of": "2026-10-10",
                "lines": [
                  {
                    "entry_number": "ABC-1234567-8",
                    "line_number": 1,
                    "hts10": "6112194050",
                    "origin": "CN",
                    "entry_date": "2025-12-07",
                    "export_date": "2025-11-17",
                    "mode": "vessel",
                    "entered_value_usd": 48250,
                    "liquidation_status": "unliquidated"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK. `data` holds the result; `meta` holds the dataset version, sources and usage.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Dataset-Version": {
                "description": "Version of the dataset that answered",
                "schema": {
                  "type": "string"
                }
              },
              "X-Request-Id": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Body over 512 KB",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Body is not application/json",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit or monthly quota exceeded",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requests per minute allowed for this key",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current minute",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Limit": {
                "description": "Units included per month in your plan on this product. Paid plans keep working above it, up to meta.usage.hard_cap_units; free plans stop at it",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Used": {
                "description": "Units used this month (including this call on success)",
                "schema": {
                  "type": "integer"
                }
              },
              "Retry-After": {
                "description": "Seconds until the rate window resets (rate limit only)",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/datasets": {
      "get": {
        "operationId": "datasets_list",
        "tags": [
          "Account"
        ],
        "summary": "Datasets and versions",
        "security": [],
        "description": "Datasets served, their versions, record counts, sources and licences, and load report.",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/v1/health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Account"
        ],
        "summary": "Service health",
        "security": [],
        "description": "Status, the tariff engine's coverage, and the loaded dataset versions.",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/v1/datasets/{name}/snapshot": {
      "get": {
        "operationId": "datasets_snapshot",
        "tags": [
          "Account"
        ],
        "summary": "Bulk snapshot (Enterprise)",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "gzip of the dataset's data.sqlite for the loaded version. Enterprise plan only. Free (0 units).",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "tariffs"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "gzip file",
            "content": {
              "application/gzip": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "application/gzip"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan does not include snapshots",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown dataset or no snapshot stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup": {
      "post": {
        "operationId": "signup",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Ask for a free API key (sends a verification email)",
        "security": [],
        "description": "Deprecated: use the dashboard on the product's website (sign in with your email). Kept working until it is retired. Step 1 of 2. Checks the Cloudflare Turnstile token, refuses disposable email domains and applies per-IP and per-email limits, then emails a single-use link valid 30 minutes. No key is issued yet. The 202 answer is the same whether or not the address already has an account. Off unless SIGNUP_ENABLED.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "accept_terms",
                  "turnstile_token"
                ],
                "additionalProperties": false,
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "accept_terms": {
                    "type": "boolean",
                    "const": true
                  },
                  "turnstile_token": {
                    "type": "string",
                    "maxLength": 2048,
                    "description": "The token from the Turnstile widget on the signup page"
                  },
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food",
                      "cosmetics"
                    ],
                    "description": "The product site the signup came from (the verification link points back to it)"
                  },
                  "attribution": {
                    "type": "object",
                    "additionalProperties": false,
                    "description": "Captured by the site when the visitor landed: UTM tags, document.referrer and the landing page URL. Only the referrer's host and the landing page's path are kept.",
                    "properties": {
                      "utm_source": {
                        "type": "string"
                      },
                      "utm_medium": {
                        "type": "string"
                      },
                      "utm_campaign": {
                        "type": "string"
                      },
                      "utm_term": {
                        "type": "string"
                      },
                      "utm_content": {
                        "type": "string"
                      },
                      "referrer": {
                        "type": "string"
                      },
                      "landing_page": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Verification email sent"
          },
          "400": {
            "description": "Invalid or disposable email, terms not accepted, or no Turnstile token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Signup is not open, or the human check failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Bot protection or email is not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup/verify": {
      "post": {
        "operationId": "signup_verify",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Confirm the email and get the free key",
        "security": [],
        "description": "Deprecated: use the dashboard on the product's website (sign in with your email). Kept working until it is retired. Step 2 of 2. Takes the token from the emailed link and creates the account with one Free key, shown once. One free key per verified email (Gmail dots and +tags count as the same address).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "additionalProperties": false,
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account and key created"
          },
          "400": {
            "description": "Invalid link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Link already used, or the email already has a key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Link expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account": {
      "get": {
        "operationId": "account_get",
        "tags": [
          "Account"
        ],
        "summary": "Your account: plans and usage per product, keys",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "products: for each product, your plan, its included monthly_units, hard_cap_units, units used this month and a usage_note in words. plan: the account-wide plan, id and name only (limits are per product). usage: this key's calls on every product. Free (0 units).",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/key/rotate": {
      "post": {
        "operationId": "account_key_rotate",
        "tags": [
          "Account"
        ],
        "summary": "Replace your key with a new one",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Issues a new secret for the same key id (the calling key unless key_id names another key of the account). The old secret stops working at once; usage and quota carry on. The new key is shown once. On an account created on the website a key can rotate only itself (403 manage_keys_on_dashboard): manage the other keys on the dashboard.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "additionalProperties": false,
                "properties": {
                  "key_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "New key"
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "key_id names another key of a self-serve account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Key not in this account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/key/revoke": {
      "post": {
        "operationId": "account_key_revoke",
        "tags": [
          "Account"
        ],
        "summary": "Revoke a key",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "The key stops working at once (the calling key unless key_id names another key of the account; on an account created on the website a key can revoke only itself, 403 manage_keys_on_dashboard). To get a new key, sign in on the product's website and create one on the dashboard.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirm"
                ],
                "additionalProperties": false,
                "properties": {
                  "key_id": {
                    "type": "string"
                  },
                  "confirm": {
                    "type": "boolean",
                    "const": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked"
          },
          "400": {
            "description": "confirm missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "key_id names another key of a self-serve account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/recover": {
      "post": {
        "operationId": "account_recover",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Lost your key: email a link to get a new one",
        "security": [],
        "description": "Deprecated: use the dashboard on the product's website (sign in with your email). Kept working until it is retired. A lost key: sign in on the website and create a new key. Checks Turnstile and per-IP and per-email limits. The 202 answer is the same whether or not the address has an account. The link is valid 15 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "turnstile_token"
                ],
                "additionalProperties": false,
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254
                  },
                  "turnstile_token": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food",
                      "cosmetics"
                    ],
                    "description": "The product site the request came from (the link points back to it; default: the product the account signed up on)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Sent if the account exists"
          },
          "400": {
            "description": "Invalid email or no Turnstile token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The human check failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account/recover/confirm": {
      "post": {
        "operationId": "account_recover_confirm",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Confirm the lost-key link and get a new key",
        "security": [],
        "description": "Deprecated: use the dashboard on the product's website (sign in with your email). Kept working until it is retired. Replaces the account's key secret (or reissues a key you revoked). Keys revoked by us are not reissued. The new key is shown once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "additionalProperties": false,
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "New key"
          },
          "400": {
            "description": "Invalid link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key revoked by us or account suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Link already used",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Link expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "usage_get",
        "tags": [
          "Account"
        ],
        "summary": "Your usage this month",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Units and calls per endpoint for the calling key, and per product: your plan, units used, included monthly_units, hard_cap_units and a usage_note in words. plan: the account-wide plan, id and name only (limits are per product). Free (0 units).",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "operationId": "products_list",
        "tags": [
          "Account"
        ],
        "summary": "Products, stages and plans with prices",
        "security": [],
        "description": "One account and one key work across products; each product has its own plan (a free tier, or a paid subscription) and its own monthly units. Waitlist products are not sold yet. Each plan lists its included monthly_units and its hard_cap_units: above the hard cap, requests get 429 quota_exceeded until the next calendar month (UTC) or an upgrade. overage_charged is false: during the beta, usage between the two is not charged and no overage price is listed. usage_note says the same in words. Enterprise volumes and limits are by contract, and products not on sale yet have no prices: their prices, units and caps are null.",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "operationId": "billing_checkout",
        "tags": [
          "Account"
        ],
        "summary": "Start a subscription for your account (Stripe Checkout)",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "For an account with a key: creates a Stripe Checkout session for one product and plan and returns its URL (data.mode: live or sandbox). The plan is added to the account of the key; the key does not change. On the websites, people upgrade from their dashboard (signed in with their email; the legacy POST /v1/billing/subscribe is deprecated). With billing off the answer is 501 with what would be created.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product",
                  "plan"
                ],
                "additionalProperties": false,
                "properties": {
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food"
                    ]
                  },
                  "plan": {
                    "type": "string",
                    "enum": [
                      "developer",
                      "pro"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout session created: data.url"
          },
          "400": {
            "description": "Unknown product or plan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Product not sold yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already subscribed: use the billing portal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "501": {
            "description": "Billing is off",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/subscribe": {
      "post": {
        "operationId": "billing_subscribe",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Buy a paid plan without a key (straight to Stripe Checkout)",
        "security": [],
        "description": "Retired: answers 410 endpoint_retired. Choose a plan on the product's website: it confirms the email with a code, then opens Stripe Checkout for the signed-in account. What it did: checks the Cloudflare Turnstile token, refuses disposable email domains and applies per-IP and per-email limits. For an address without an account: 201 with a Stripe Checkout URL for the product and plan (the page closes after 60 minutes). No account and no key exist until Stripe confirms the payment; an abandoned checkout creates nothing. data.claim is a one-time secret for the page the buyer returns to: keep it in the browser that pays (never in a URL) and send it to POST /v1/billing/claim after payment to see the API key once. For an address that already has an account: 202 link_sent, with no checkout. The mailbox gets a link (valid 30 minutes) that adds the plan to that account; its key stays the same. (With the account's key, POST /v1/billing/checkout does the same.) A newer checkout for the same address and product closes an older open one. Off unless SIGNUP_ENABLED; 501 while billing is off.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "product",
                  "plan",
                  "accept_terms",
                  "turnstile_token"
                ],
                "additionalProperties": false,
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "accept_terms": {
                    "type": "boolean",
                    "const": true
                  },
                  "turnstile_token": {
                    "type": "string",
                    "maxLength": 2048,
                    "description": "The token from the Turnstile widget on the subscribe page (action subscribe)"
                  },
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food"
                    ]
                  },
                  "plan": {
                    "type": "string",
                    "enum": [
                      "developer",
                      "pro"
                    ]
                  },
                  "attribution": {
                    "type": "object",
                    "additionalProperties": false,
                    "description": "As for POST /v1/signup: landing UTM tags, referrer and landing page",
                    "properties": {
                      "utm_source": {
                        "type": "string"
                      },
                      "utm_medium": {
                        "type": "string"
                      },
                      "utm_campaign": {
                        "type": "string"
                      },
                      "utm_term": {
                        "type": "string"
                      },
                      "utm_content": {
                        "type": "string"
                      },
                      "referrer": {
                        "type": "string"
                      },
                      "landing_page": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "New address: data.url (Stripe Checkout), data.session_id and data.claim (keep it in the browser)"
          },
          "202": {
            "description": "The address has an account: a link to continue was emailed to it (data.status link_sent)"
          },
          "400": {
            "description": "Invalid or disposable email, unknown product or plan, terms not accepted, or no Turnstile token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Signup is not open, the product is not sold yet, or the human check failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Retired: choose a plan on the product's website",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "501": {
            "description": "Billing is off",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Billing, bot protection or email is not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/subscribe/confirm": {
      "post": {
        "operationId": "billing_subscribe_confirm",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "Continue from the emailed upgrade link to Stripe Checkout",
        "security": [],
        "description": "Retired: answers 410 endpoint_retired. Use the dashboard on the product's website (sign in with your email). What it did: took the token of the link that POST /v1/billing/subscribe emailed to an address with an account (the mailbox proved ownership) and opened Stripe Checkout for that account and its Stripe customer, with the same answer as POST /v1/billing/subscribe for a new address (url, session_id, claim).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "additionalProperties": false,
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout session created: data.url, data.session_id, data.claim"
          },
          "400": {
            "description": "Invalid link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Account suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Link already used, or the account already has a plan for this product (use the billing portal)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Retired (endpoint_retired), or the link expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "501": {
            "description": "Billing is off",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/claim": {
      "post": {
        "operationId": "billing_claim",
        "deprecated": true,
        "tags": [
          "Account"
        ],
        "summary": "After payment: the plan, and the API key once",
        "security": [],
        "description": "Deprecated: use the dashboard on the product's website (sign in with your email). Kept working until it is retired. Called by the page Stripe returns to (it adds session_id to the address) with the claim secret from the same browser. 202 pending until the Stripe webhook has recorded the payment; then once: status key_issued with the api_key of the account the payment created (shown once, stored only as a hash), or status plan_active with no key when the plan went to an account that already existed (its key does not change). The claim works for 120 minutes after the checkout started. A key that was not saved: sign in on the website and create a key on the dashboard.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "session_id",
                  "claim"
                ],
                "additionalProperties": false,
                "properties": {
                  "session_id": {
                    "type": "string",
                    "description": "cs_… from the page address"
                  },
                  "claim": {
                    "type": "string",
                    "description": "data.claim of POST /v1/billing/subscribe or /subscribe/confirm"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "data.status key_issued (with data.api_key) or plan_active"
          },
          "202": {
            "description": "data.status pending: Stripe has not confirmed the payment yet; ask again in a few seconds"
          },
          "400": {
            "description": "Unknown claim, or one that belongs to another checkout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Account suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already shown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "Expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/portal": {
      "post": {
        "operationId": "billing_portal",
        "tags": [
          "Account"
        ],
        "summary": "Manage subscriptions (Stripe Customer Portal)",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Returns a Customer Portal URL to change plan, cancel (at period end), update the card or download invoices. Without product, the portal of the product the account subscribes to.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [],
                "additionalProperties": false,
                "properties": {
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Portal session created: data.url"
          },
          "400": {
            "description": "Unknown product, or no product named and no subscription to take it from",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Product not sold yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No subscription yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "501": {
            "description": "Billing is off",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/waitlist": {
      "post": {
        "operationId": "waitlist_join",
        "tags": [
          "Account"
        ],
        "summary": "Join a product's waitlist",
        "security": [],
        "description": "For products not sold yet. Same 202 answer whether or not the address is already on the list.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product",
                  "email",
                  "consent"
                ],
                "additionalProperties": false,
                "properties": {
                  "product": {
                    "type": "string",
                    "enum": [
                      "tariffs",
                      "food",
                      "cosmetics"
                    ]
                  },
                  "email": {
                    "type": "string",
                    "maxLength": 254
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "company": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "use_case": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "consent": {
                    "type": "boolean",
                    "const": true
                  },
                  "turnstile_token": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "attribution": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "On the waitlist"
          },
          "400": {
            "description": "Invalid email, product or missing consent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The human check failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/client-errors": {
      "post": {
        "operationId": "client_errors",
        "tags": [
          "Account"
        ],
        "summary": "Report a browser error from one of our sites",
        "security": [],
        "description": "Used by the sites' error handler. Only the page path is kept (no query or fragment). Rate-limited per IP.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "additionalProperties": false,
                "properties": {
                  "message": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "name": {
                    "type": "string"
                  },
                  "stack": {
                    "type": "string",
                    "maxLength": 8000
                  },
                  "page": {
                    "type": "string"
                  },
                  "source": {
                    "type": "string"
                  },
                  "product": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "error",
                      "unhandledrejection"
                    ]
                  },
                  "release": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted"
          },
          "400": {
            "description": "No message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many attempts from this IP, email or account (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/samples": {
      "get": {
        "operationId": "demo_samples",
        "tags": [
          "Demo"
        ],
        "summary": "Sample requests the demo answers",
        "security": [],
        "description": "The allow-listed sample requests per product and operation (from the product registry): the inputs the public demo answers without a key, and the values each sample may vary. meta.free_calculator: the operations and fields the free duty calculator may send for any HTS code, and its daily limit per IP address.",
        "parameters": [
          {
            "name": "product",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "tariffs",
                "food",
                "cosmetics"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/demo/v1/tariffs/duty-stack": {
      "post": {
        "operationId": "demo_tariffs_duty_stack",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_duty_stack",
        "security": [],
        "summary": "Demo: Duty stack for an HTS code, origin and date",
        "description": "POST /v1/tariffs/duty-stack without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants), and, as the free duty calculator, for any HTS code, origin and entry date the API accepts with the fields hts10, origin, entry_date, entered_value_usd only: 10 calculations a day per IP address, counted apart from the samples. The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to POST /v1/tariffs/duty-stack instead.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_duty_stack_body"
              },
              "example": {
                "hts10": "6112194050",
                "origin": "CN",
                "entry_date": "2025-08-20",
                "entered_value_usd": 10000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached, or the free calculator's daily limit (free_calculator_limit)",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/duty-stack/batch": {
      "post": {
        "operationId": "demo_tariffs_duty_stack_batch",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_duty_stack_batch",
        "security": [],
        "summary": "Demo: Duty stacks for many lines",
        "description": "POST /v1/tariffs/duty-stack/batch without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to POST /v1/tariffs/duty-stack/batch instead.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_duty_stack_batch_body"
              },
              "example": {
                "lines": [
                  {
                    "line_id": "A1",
                    "hts10": "7318158066",
                    "origin": "CN",
                    "entry_date": "2025-08-20",
                    "entered_value_usd": 10000
                  },
                  {
                    "line_id": "A2",
                    "hts10": "8471300100",
                    "origin": "VN",
                    "entry_date": "2025-09-15",
                    "entered_value_usd": 120000
                  },
                  {
                    "line_id": "A3",
                    "hts10": "6112194050",
                    "origin": "MX",
                    "entry_date": "2026-03-02",
                    "entered_value_usd": 5000
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/compare-origins": {
      "post": {
        "operationId": "demo_tariffs_compare_origins",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_compare_origins",
        "security": [],
        "summary": "Demo: Compare origins for one HTS code",
        "description": "POST /v1/tariffs/compare-origins without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants), and, as the free duty calculator, for any HTS code, origin and entry date the API accepts with the fields hts10, origins, entry_date, entered_value_usd only: 10 calculations a day per IP address, counted apart from the samples. The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to POST /v1/tariffs/compare-origins instead.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_compare_origins_body"
              },
              "example": {
                "hts10": "6112194050",
                "origins": [
                  "CN",
                  "VN",
                  "IN",
                  "MX",
                  "BD",
                  "DE"
                ],
                "entry_date": "2026-10-09",
                "entered_value_usd": 10000
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached, or the free calculator's daily limit (free_calculator_limit)",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/hts/search": {
      "get": {
        "operationId": "demo_tariffs_hts_search",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_hts_search",
        "security": [],
        "summary": "Demo: Search the tariff schedule's text",
        "description": "GET /v1/tariffs/hts/search without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/hts/search instead.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            },
            "example": "cap screws"
          },
          {
            "name": "chapter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^\\d{2}$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "example": 5
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "relevance: how well the lines' text matches the words (the 500 lines with the most words in their own text are ranked); schedule: chapter, then line, through all matches",
            "schema": {
              "type": "string",
              "enum": [
                "relevance",
                "schedule"
              ],
              "default": "relevance"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/hts/{hts}": {
      "get": {
        "operationId": "demo_tariffs_hts",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_hts",
        "security": [],
        "summary": "Demo: HTS line lookup",
        "description": "GET /v1/tariffs/hts/{hts} without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/hts/{hts} instead.",
        "parameters": [
          {
            "name": "hts",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{8,13}$"
            },
            "example": "6112194050"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2025-12-07"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/hts/{hts}/history": {
      "get": {
        "operationId": "demo_tariffs_hts_history",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_hts_history",
        "security": [],
        "summary": "Demo: Revision history of an HTS line",
        "description": "GET /v1/tariffs/hts/{hts}/history without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/hts/{hts}/history instead.",
        "parameters": [
          {
            "name": "hts",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{10,13}$"
            },
            "example": "0901110035"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/revisions": {
      "get": {
        "operationId": "demo_tariffs_revisions",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_revisions",
        "security": [],
        "summary": "Demo: HTS revisions",
        "description": "GET /v1/tariffs/revisions without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/revisions instead.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2026-09-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/measures/{heading}": {
      "get": {
        "operationId": "demo_tariffs_measure",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_measure",
        "security": [],
        "summary": "Demo: A Chapter 99 measure",
        "description": "GET /v1/tariffs/measures/{heading} without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/measures/{heading} instead.",
        "parameters": [
          {
            "name": "heading",
            "in": "path",
            "required": true,
            "description": "Chapter 99 heading (e.g. 9903.01.24, 9904.02.01) or a rule_id (e.g. OTH-122-POSTAL; encode / as %2F)",
            "schema": {
              "type": "string",
              "pattern": "^(99\\d{2}\\.\\d{2}\\.\\d{2}|[A-Za-z0-9][A-Za-z0-9_./-]{2,59})$"
            },
            "example": "9903.01.24"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/measures": {
      "get": {
        "operationId": "demo_tariffs_measures",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_measures",
        "security": [],
        "summary": "Demo: Measures that reach an HTS code",
        "description": "GET /v1/tariffs/measures without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/measures instead.",
        "parameters": [
          {
            "name": "hts",
            "in": "query",
            "required": true,
            "description": "HTS heading, subheading or line (4 to 10 digits)",
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{4,13}$"
            },
            "example": "7318158066"
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "example": "CN"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2025-08-20"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 10
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 10000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/changes": {
      "get": {
        "operationId": "demo_tariffs_changes",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_changes",
        "security": [],
        "summary": "Demo: Tariff change feed",
        "description": "GET /v1/tariffs/changes without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to GET /v1/tariffs/changes instead.",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "required": true,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            },
            "example": "2026-09-01"
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "measure",
                "hts_line",
                "base_rate"
              ]
            }
          },
          {
            "name": "hts",
            "in": "query",
            "required": false,
            "description": "Only changes reaching this heading, subheading or line; each measure event says how it reaches the code (scope_match: listed, all goods except listed codes, or a description the code alone does not settle)",
            "schema": {
              "type": "string",
              "pattern": "^[0-9.]{4,13}$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "example": 20
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/demo/v1/tariffs/ieepa-refund": {
      "post": {
        "operationId": "demo_tariffs_ieepa_refund",
        "tags": [
          "Demo"
        ],
        "x-product": "tariffs",
        "x-demo-of": "tariffs_ieepa_refund",
        "security": [],
        "summary": "Demo: IEEPA refund calculation for entry lines",
        "description": "POST /v1/tariffs/ieepa-refund without a key, for the sample inputs that GET /demo/samples lists for it (every field equal to the sample's value or to one of its listed variants). The answer is the endpoint's real output, marked meta.demo = true, not metered. Limits per IP address: 30 sample requests a minute and 200 a day. Any other input answers 403 demo_not_allowed: send your API key to POST /v1/tariffs/ieepa-refund instead.",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tariffs_ieepa_refund_body"
              },
              "example": {
                "as_of": "2026-10-10",
                "lines": [
                  {
                    "entry_number": "ABC-1234567-8",
                    "line_number": 1,
                    "hts10": "6112194050",
                    "origin": "CN",
                    "entry_date": "2025-12-07",
                    "export_date": "2025-11-17",
                    "mode": "vessel",
                    "entered_value_usd": 48250,
                    "liquidation_status": "unliquidated"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The endpoint's output, marked as a demo (meta.demo = true, meta.demo_kind sample or free_calculator; no usage)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {},
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Input not in the demo allow-list (demo_not_allowed), or the product is not open yet (product_not_available)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Valid request that cannot be computed (e.g. out of coverage)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Demo limit for this IP address reached",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the limit's window resets",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Demo switched off, or dataset not loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "tags": [
          "MCP"
        ],
        "summary": "MCP server (Streamable HTTP, JSON-RPC 2.0)",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Model Context Protocol endpoint for AI agents. Methods: initialize, tools/list, tools/call, ping. Every REST operation above is a tool with the same input schema and the same metering.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response"
          },
          "202": {
            "description": "Notification accepted"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "required": [
          "request_id",
          "dataset",
          "dataset_version",
          "data_status",
          "sources",
          "disclaimer"
        ],
        "properties": {
          "request_id": {
            "type": "string"
          },
          "api_version": {
            "type": "string"
          },
          "dataset": {
            "type": "string",
            "enum": [
              "food",
              "tariffs",
              "cosmetics"
            ]
          },
          "dataset_version": {
            "type": "string"
          },
          "dataset_built_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "data_status": {
            "type": "string",
            "enum": [
              "released"
            ],
            "description": "released = served from the dataset's released build (dist/data.sqlite)"
          },
          "data_status_note": {
            "type": "string"
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "licence": {
                  "type": "string"
                },
                "commercial_redistribution_ok": {
                  "type": "boolean"
                }
              }
            }
          },
          "provenance_note": {
            "type": "string"
          },
          "disclaimer": {
            "type": "string"
          },
          "usage": {
            "type": [
              "object",
              "null"
            ],
            "description": "Your usage on answers to your API key; null on demo answers.",
            "properties": {
              "plan": {
                "type": "string",
                "description": "Your plan on this product"
              },
              "product": {
                "type": "string"
              },
              "period": {
                "type": "string",
                "description": "Calendar month (UTC), YYYY-MM"
              },
              "units_charged": {
                "type": "integer",
                "description": "Units this call counted against your monthly units (a count, not money)"
              },
              "units_used": {
                "type": "integer",
                "description": "Units used on this product this month, including this call"
              },
              "monthly_units": {
                "type": "integer",
                "description": "Units included in your plan each month (the X-Quota-Limit header)"
              },
              "hard_cap_units": {
                "type": "integer",
                "description": "Requests are refused (429 quota_exceeded) above this many units in the month. Free plans: the included units; paid plans: a multiple of them"
              },
              "above_included_units": {
                "type": "boolean",
                "description": "This month's usage is above the included units (paid plans keep working up to hard_cap_units)"
              },
              "overage_charged": {
                "type": "boolean",
                "description": "Whether usage above the included units is charged. false during the beta"
              },
              "overage": {
                "type": "boolean",
                "deprecated": true,
                "description": "Older name of above_included_units, kept for existing clients. It is not a charge"
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "request_id": {
                "type": "string"
              }
            }
          }
        }
      },
      "food_barcode_batch_body": {
        "type": "object",
        "required": [
          "gtins"
        ],
        "additionalProperties": false,
        "properties": {
          "gtins": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "string",
              "pattern": "^[0-9 -]{8,20}$"
            }
          }
        }
      },
      "food_analyze_body": {
        "type": "object",
        "required": [
          "lines"
        ],
        "additionalProperties": false,
        "properties": {
          "lines": {
            "type": "array",
            "minItems": 1,
            "maxItems": 60,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "fr",
              "de",
              "it",
              "es"
            ],
            "default": "en",
            "description": "Language of the food names in the lines"
          },
          "servings": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "alternatives": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5,
            "default": 3
          }
        }
      },
      "food_meal_match_body": {
        "type": "object",
        "required": [
          "items"
        ],
        "additionalProperties": false,
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 30,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "label": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "What the food is, e.g. 'spaghetti bolognese' or '2 scrambled eggs'"
                },
                "grams": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "maximum": 5000
                },
                "quantity": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "maximum": 100
                },
                "unit": {
                  "type": "string",
                  "maxLength": 30,
                  "description": "cup, tbsp (T), tsp (t), slice, piece, serving, oz, g... (with quantity)"
                },
                "food_id": {
                  "type": "string",
                  "pattern": "^(fdc|ciqual|dish):[A-Za-z0-9_.-]{1,40}$",
                  "description": "A food you already know (skips matching)"
                },
                "gtin": {
                  "type": "string",
                  "pattern": "^[0-9 -]{8,20}$",
                  "description": "Barcode of a packaged food (label values)"
                }
              }
            }
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "fr",
              "de",
              "it",
              "es"
            ],
            "default": "en"
          },
          "alternatives": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5,
            "default": 3
          }
        }
      },
      "food_recipe_body": {
        "type": "object",
        "required": [
          "cooked",
          "ingredients"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "cooked": {
            "type": "boolean",
            "description": "false: no heat step (tier T0); true: cooked (T1-T3 from the references used)"
          },
          "servings": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "ingredients": {
            "type": "array",
            "minItems": 1,
            "maxItems": 60,
            "items": {
              "type": "object",
              "required": [
                "food"
              ],
              "additionalProperties": false,
              "properties": {
                "food": {
                  "type": "string",
                  "pattern": "^(fdc|ciqual|gtin|fdc_branded):[0-9A-Za-z]{1,20}$",
                  "description": "Ingredient food: fdc:<FDC id>, ciqual:<code>, gtin:<GTIN-14> (per-100 g products only) or fdc_branded:<FDC id>"
                },
                "grams": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "maximum": 100000,
                  "description": "Grams as written in the recipe (raw weight)"
                },
                "label": {
                  "type": "string",
                  "maxLength": 200
                },
                "convert": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "Enter the ingredient as a cooked record of the same food",
                  "properties": {
                    "to_cooked": {
                      "type": "string",
                      "pattern": "^(fdc|ciqual|gtin|fdc_branded):[0-9A-Za-z]{1,20}$",
                      "description": "Ingredient food: fdc:<FDC id>, ciqual:<code>, gtin:<GTIN-14> (per-100 g products only) or fdc_branded:<FDC id>"
                    },
                    "yield": {
                      "type": "object",
                      "additionalProperties": false,
                      "description": "Weight raw -> cooked from a cited yield (else dry-matter balance between the two records)",
                      "properties": {
                        "fndds_moisture": {
                          "type": "integer",
                          "description": "FNDDS 2021-2023 food code: its recipe moisture change"
                        },
                        "meat_yield_row": {
                          "type": "integer",
                          "description": "Row of the USDA Table of Cooking Yields for Meat and Poultry"
                        },
                        "fat": {
                          "type": "string",
                          "enum": [
                            "drained",
                            "kept"
                          ],
                          "description": "meat_yield_row: 'drained' removes the fat change (only when the method drains fat)"
                        },
                        "ah102_item": {
                          "type": "integer",
                          "description": "Verified row of USDA Agriculture Handbook 102"
                        },
                        "evaporate_all_water": {
                          "type": "boolean",
                          "description": "All water of the ingredient cooks off (flagged as estimated, T3)"
                        },
                        "match": {
                          "type": "string",
                          "enum": [
                            "same_food",
                            "analog"
                          ],
                          "description": "analog: the yield of a similar food (flags the result T3 estimated)"
                        },
                        "sr_refuse_portion": {
                          "type": "object",
                          "required": [
                            "food",
                            "seq"
                          ],
                          "additionalProperties": false,
                          "properties": {
                            "food": {
                              "type": "string",
                              "pattern": "^(fdc|ciqual|gtin|fdc_branded):[0-9A-Za-z]{1,20}$",
                              "description": "Ingredient food: fdc:<FDC id>, ciqual:<code>, gtin:<GTIN-14> (per-100 g products only) or fdc_branded:<FDC id>"
                            },
                            "seq": {
                              "type": "integer",
                              "minimum": 1
                            }
                          },
                          "description": "SR 'yield from 1 lb raw' portion"
                        }
                      }
                    },
                    "edible_ah102": {
                      "type": "integer",
                      "description": "AH-102 item for the edible portion (refuse removed)"
                    },
                    "match": {
                      "type": "string",
                      "enum": [
                        "same_food",
                        "analog"
                      ]
                    }
                  }
                },
                "cook": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "One cited weight-change source (from GET /v1/food/cooking-yields): exactly one of fndds_moisture, meat_yield_row, ah102_item, evaporate_all_water",
                  "properties": {
                    "fndds_moisture": {
                      "type": "integer",
                      "description": "FNDDS 2021-2023 food code: its recipe moisture change"
                    },
                    "meat_yield_row": {
                      "type": "integer",
                      "description": "Row of the USDA Table of Cooking Yields for Meat and Poultry"
                    },
                    "fat": {
                      "type": "string",
                      "enum": [
                        "drained",
                        "kept"
                      ],
                      "description": "meat_yield_row: 'drained' removes the fat change (only when the method drains fat)"
                    },
                    "ah102_item": {
                      "type": "integer",
                      "description": "Verified row of USDA Agriculture Handbook 102"
                    },
                    "evaporate_all_water": {
                      "type": "boolean",
                      "description": "All water of the ingredient cooks off (flagged as estimated, T3)"
                    },
                    "match": {
                      "type": "string",
                      "enum": [
                        "same_food",
                        "analog"
                      ],
                      "description": "analog: the yield of a similar food (flags the result T3 estimated)"
                    }
                  }
                },
                "retention_code": {
                  "type": "integer",
                  "minimum": 1,
                  "description": "USDA Release 6 nutrient retention code (minerals; alcohol with its energy)"
                },
                "grams_rule": {
                  "type": "object",
                  "required": [
                    "fndds_ratio"
                  ],
                  "additionalProperties": false,
                  "description": "Grams from an FNDDS recipe ratio (e.g. water absorbed per gram of rice)",
                  "properties": {
                    "fndds_ratio": {
                      "type": "object",
                      "required": [
                        "food_code",
                        "ingredient_codes",
                        "per_codes",
                        "of"
                      ],
                      "additionalProperties": false,
                      "properties": {
                        "food_code": {
                          "type": "integer"
                        },
                        "ingredient_codes": {
                          "type": "array",
                          "items": {
                            "type": "integer"
                          }
                        },
                        "per_codes": {
                          "type": "array",
                          "items": {
                            "type": "integer"
                          }
                        },
                        "of": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "description": "0-based indexes of earlier ingredients the ratio applies to"
                        }
                      }
                    },
                    "match": {
                      "type": "string",
                      "enum": [
                        "same_food",
                        "analog"
                      ]
                    }
                  }
                }
              }
            }
          },
          "hydrate": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "object",
              "required": [
                "members",
                "like"
              ],
              "additionalProperties": false,
              "properties": {
                "members": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "like": {
                  "type": "string",
                  "pattern": "^(fdc|ciqual|gtin|fdc_branded):[0-9A-Za-z]{1,20}$",
                  "description": "Ingredient food: fdc:<FDC id>, ciqual:<code>, gtin:<GTIN-14> (per-100 g products only) or fdc_branded:<FDC id>"
                },
                "match": {
                  "type": "string",
                  "enum": [
                    "same_food",
                    "analog"
                  ]
                }
              }
            },
            "description": "Bring a group of ingredients to the water content of a cooked record (e.g. a dough)"
          },
          "group_cook": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "object",
              "required": [
                "members",
                "cook"
              ],
              "additionalProperties": false,
              "properties": {
                "members": {
                  "type": "array",
                  "items": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "cook": {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "One cited weight-change source (from GET /v1/food/cooking-yields): exactly one of fndds_moisture, meat_yield_row, ah102_item, evaporate_all_water",
                  "properties": {
                    "fndds_moisture": {
                      "type": "integer",
                      "description": "FNDDS 2021-2023 food code: its recipe moisture change"
                    },
                    "meat_yield_row": {
                      "type": "integer",
                      "description": "Row of the USDA Table of Cooking Yields for Meat and Poultry"
                    },
                    "fat": {
                      "type": "string",
                      "enum": [
                        "drained",
                        "kept"
                      ],
                      "description": "meat_yield_row: 'drained' removes the fat change (only when the method drains fat)"
                    },
                    "ah102_item": {
                      "type": "integer",
                      "description": "Verified row of USDA Agriculture Handbook 102"
                    },
                    "evaporate_all_water": {
                      "type": "boolean",
                      "description": "All water of the ingredient cooks off (flagged as estimated, T3)"
                    },
                    "match": {
                      "type": "string",
                      "enum": [
                        "same_food",
                        "analog"
                      ],
                      "description": "analog: the yield of a similar food (flags the result T3 estimated)"
                    }
                  }
                }
              }
            },
            "description": "Weight change of a group of ingredients (e.g. a sauce reduced)"
          },
          "dish_cook": {
            "type": "object",
            "additionalProperties": false,
            "description": "One cited weight-change source (from GET /v1/food/cooking-yields): exactly one of fndds_moisture, meat_yield_row, ah102_item, evaporate_all_water",
            "properties": {
              "fndds_moisture": {
                "type": "integer",
                "description": "FNDDS 2021-2023 food code: its recipe moisture change"
              },
              "meat_yield_row": {
                "type": "integer",
                "description": "Row of the USDA Table of Cooking Yields for Meat and Poultry"
              },
              "fat": {
                "type": "string",
                "enum": [
                  "drained",
                  "kept"
                ],
                "description": "meat_yield_row: 'drained' removes the fat change (only when the method drains fat)"
              },
              "ah102_item": {
                "type": "integer",
                "description": "Verified row of USDA Agriculture Handbook 102"
              },
              "evaporate_all_water": {
                "type": "boolean",
                "description": "All water of the ingredient cooks off (flagged as estimated, T3)"
              },
              "match": {
                "type": "string",
                "enum": [
                  "same_food",
                  "analog"
                ],
                "description": "analog: the yield of a similar food (flags the result T3 estimated)"
              }
            }
          },
          "uncovered_heat_steps": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Heat steps you know of that have no USDA yield (flags the result T3)"
          },
          "retention_code": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "tariffs_duty_stack_body": {
        "type": "object",
        "required": [
          "hts10",
          "origin",
          "entry_date"
        ],
        "additionalProperties": false,
        "properties": {
          "hts10": {
            "type": "string",
            "pattern": "^[0-9.]{10,13}$",
            "description": "10-digit HTSUS statistical number"
          },
          "origin": {
            "type": "string",
            "pattern": "^[A-Za-z]{2}$",
            "description": "Country of origin, ISO 3166-1 alpha-2"
          },
          "entry_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "export_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "mode": {
            "type": "string",
            "enum": [
              "vessel",
              "air",
              "truck",
              "rail",
              "mail",
              "postal",
              "other"
            ]
          },
          "declared_attributes": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "Facts you declare, e.g. steel_content_value_share, usmca_qualifying"
          },
          "entered_value_usd": {
            "type": [
              "number",
              "string"
            ],
            "description": "Entered (customs) value in USD: adds the duty in dollars (amounts)"
          }
        }
      },
      "tariffs_duty_stack_batch_body": {
        "type": "object",
        "required": [
          "lines"
        ],
        "additionalProperties": false,
        "properties": {
          "lines": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "hts10",
                "origin",
                "entry_date"
              ],
              "properties": {
                "line_id": {
                  "type": "string",
                  "maxLength": 40
                },
                "hts10": {
                  "type": "string",
                  "pattern": "^[0-9.]{10,13}$",
                  "description": "10-digit HTSUS statistical number"
                },
                "origin": {
                  "type": "string",
                  "pattern": "^[A-Za-z]{2}$"
                },
                "entry_date": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "export_date": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "vessel",
                    "air",
                    "truck",
                    "rail",
                    "mail",
                    "postal",
                    "other"
                  ]
                },
                "declared_attributes": {
                  "type": "object",
                  "additionalProperties": {
                    "type": [
                      "string",
                      "number",
                      "boolean"
                    ]
                  }
                },
                "entered_value_usd": {
                  "type": [
                    "number",
                    "string"
                  ],
                  "description": "Entered (customs) value in USD: adds the duty in dollars (amounts)"
                }
              }
            }
          }
        }
      },
      "tariffs_compare_origins_body": {
        "type": "object",
        "required": [
          "hts10",
          "origins",
          "entry_date"
        ],
        "additionalProperties": false,
        "properties": {
          "hts10": {
            "type": "string",
            "pattern": "^[0-9.]{10,13}$"
          },
          "origins": {
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          },
          "entry_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "export_date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "mode": {
            "type": "string",
            "enum": [
              "vessel",
              "air",
              "truck",
              "rail",
              "mail",
              "postal",
              "other"
            ]
          },
          "declared_attributes": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            }
          },
          "entered_value_usd": {
            "type": [
              "number",
              "string"
            ],
            "description": "Entered (customs) value in USD: adds the duty in dollars (amounts)"
          }
        }
      },
      "tariffs_ieepa_refund_body": {
        "type": "object",
        "required": [
          "lines"
        ],
        "additionalProperties": false,
        "properties": {
          "as_of": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "lines": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "hts10",
                "origin",
                "entry_date",
                "entered_value_usd"
              ],
              "properties": {
                "line_id": {
                  "type": "string",
                  "maxLength": 40
                },
                "entry_number": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 20
                },
                "line_number": {
                  "type": "integer",
                  "minimum": 1
                },
                "hts10": {
                  "type": "string",
                  "pattern": "^[0-9.]{10,13}$",
                  "description": "10-digit HTSUS number from the entry summary (you supply it; we do not classify)"
                },
                "origin": {
                  "type": "string",
                  "pattern": "^[A-Za-z]{2}$"
                },
                "entry_date": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "export_date": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "vessel",
                    "air",
                    "truck",
                    "rail",
                    "mail",
                    "postal",
                    "other"
                  ]
                },
                "entered_value_usd": {
                  "type": [
                    "number",
                    "string"
                  ],
                  "description": "Entered (customs) value in USD"
                },
                "declared_attributes": {
                  "type": "object",
                  "additionalProperties": {
                    "type": [
                      "string",
                      "number",
                      "boolean"
                    ]
                  }
                },
                "ieepa_duty_paid_usd": {
                  "type": [
                    "number",
                    "string"
                  ],
                  "description": "IEEPA duty actually paid on the line (ACE ES-003), if known"
                },
                "liquidation_status": {
                  "type": "string",
                  "enum": [
                    "unliquidated",
                    "liquidated",
                    "extended",
                    "suspended",
                    "under_review"
                  ]
                },
                "liquidation_date": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "reconciliation_flag": {
                  "type": "boolean"
                },
                "reconciliation_entry_on_file": {
                  "type": "boolean"
                },
                "entry_type": {
                  "type": "string",
                  "pattern": "^\\d{1,2}$",
                  "description": "CBP entry type code, e.g. 01, 11, 21"
                },
                "ace_filed": {
                  "type": "boolean"
                },
                "drawback_designated": {
                  "type": "boolean"
                },
                "open_protest": {
                  "type": "boolean"
                },
                "adcvd_pending": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "cosmetics_formula_check_body": {
        "type": "object",
        "required": [
          "markets",
          "product_category",
          "ingredients"
        ],
        "additionalProperties": false,
        "properties": {
          "markets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 11,
            "items": {
              "type": "string",
              "enum": [
                "EU",
                "GB",
                "US",
                "US-CA",
                "US-CO",
                "US-MD",
                "US-ME",
                "US-MN",
                "US-OR",
                "US-VT",
                "US-WA"
              ],
              "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
            }
          },
          "product_category": {
            "type": "string",
            "maxLength": 64,
            "description": "GET /v1/cosmetics/categories"
          },
          "as_of": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "mode": {
            "type": "string",
            "enum": [
              "placing",
              "making_available"
            ],
            "default": "placing"
          },
          "children_under_3": {
            "type": "boolean"
          },
          "professional_use": {
            "type": "boolean"
          },
          "mixing_ratio": {
            "type": "string",
            "pattern": "^\\s*\\d+(\\.\\d+)?\\s*:\\s*\\d+(\\.\\d+)?\\s*$",
            "description": "Oxidative hair or eyelash dye: product:developer, e.g. '1:1'"
          },
          "formaldehyde_released_pct": {
            "type": [
              "number",
              "string",
              "null"
            ],
            "description": "Maximum theoretical releasable formaldehyde of the whole product, from every source, percent w/w. Settles the 'releases formaldehyde' label and the Annex II bans that apply only at or above 0,1 % (II/1605-1607). null or omitted = not known: never treated as 0"
          },
          "contaminants_ppm": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "number",
                "string"
              ]
            },
            "description": "Measured contaminants, e.g. {\"lead\": 2, \"1,4-dioxane\": 1}"
          },
          "ingredients": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "inci": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "INCI name as on the label"
                },
                "cas": {
                  "type": "string",
                  "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                  "description": "CAS number"
                },
                "ec": {
                  "type": "string",
                  "pattern": "^\\d{3}-\\d{3}-\\d$",
                  "description": "EC (EINECS / ELINCS) number"
                },
                "name": {
                  "type": "string",
                  "maxLength": 200,
                  "description": "Other name (chemical name)"
                },
                "pct": {
                  "type": [
                    "number",
                    "string",
                    "null"
                  ],
                  "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                },
                "function": {
                  "type": "string",
                  "maxLength": 40,
                  "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
                },
                "basis": {
                  "type": "string",
                  "maxLength": 60,
                  "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
                },
                "intentionally_added": {
                  "type": "boolean",
                  "description": "false for trace/contaminant presence (threshold rules)"
                },
                "flags": {
                  "type": "array",
                  "maxItems": 5,
                  "items": {
                    "type": "string",
                    "enum": [
                      "pfas",
                      "ortho_phthalate",
                      "formaldehyde_releaser"
                    ]
                  },
                  "description": "Class membership you know (class bans cannot be settled from a name)"
                }
              }
            }
          }
        }
      },
      "cosmetics_formula_check_batch_body": {
        "type": "object",
        "required": [
          "formulas"
        ],
        "additionalProperties": false,
        "properties": {
          "formulas": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "markets",
                "product_category",
                "ingredients"
              ],
              "additionalProperties": false,
              "properties": {
                "id": {
                  "type": "string",
                  "maxLength": 60
                },
                "markets": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 11,
                  "items": {
                    "type": "string",
                    "enum": [
                      "EU",
                      "GB",
                      "US",
                      "US-CA",
                      "US-CO",
                      "US-MD",
                      "US-ME",
                      "US-MN",
                      "US-OR",
                      "US-VT",
                      "US-WA"
                    ],
                    "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
                  }
                },
                "product_category": {
                  "type": "string",
                  "maxLength": 64
                },
                "as_of": {
                  "type": "string",
                  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                  "description": "YYYY-MM-DD"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "placing",
                    "making_available"
                  ]
                },
                "children_under_3": {
                  "type": "boolean"
                },
                "professional_use": {
                  "type": "boolean"
                },
                "mixing_ratio": {
                  "type": "string",
                  "pattern": "^\\s*\\d+(\\.\\d+)?\\s*:\\s*\\d+(\\.\\d+)?\\s*$"
                },
                "formaldehyde_released_pct": {
                  "type": [
                    "number",
                    "string",
                    "null"
                  ],
                  "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                },
                "contaminants_ppm": {
                  "type": "object",
                  "additionalProperties": {
                    "type": [
                      "number",
                      "string"
                    ]
                  }
                },
                "ingredients": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 200,
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "inci": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "description": "INCI name as on the label"
                      },
                      "cas": {
                        "type": "string",
                        "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                        "description": "CAS number"
                      },
                      "ec": {
                        "type": "string",
                        "pattern": "^\\d{3}-\\d{3}-\\d$",
                        "description": "EC (EINECS / ELINCS) number"
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "Other name (chemical name)"
                      },
                      "pct": {
                        "type": [
                          "number",
                          "string",
                          "null"
                        ],
                        "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                      },
                      "function": {
                        "type": "string",
                        "maxLength": 40,
                        "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
                      },
                      "basis": {
                        "type": "string",
                        "maxLength": 60,
                        "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
                      },
                      "intentionally_added": {
                        "type": "boolean",
                        "description": "false for trace/contaminant presence (threshold rules)"
                      },
                      "flags": {
                        "type": "array",
                        "maxItems": 5,
                        "items": {
                          "type": "string",
                          "enum": [
                            "pfas",
                            "ortho_phthalate",
                            "formaldehyde_releaser"
                          ]
                        },
                        "description": "Class membership you know (class bans cannot be settled from a name)"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "cosmetics_allergen_label_body": {
        "type": "object",
        "required": [
          "markets"
        ],
        "additionalProperties": false,
        "properties": {
          "markets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2,
            "items": {
              "type": "string",
              "enum": [
                "EU",
                "GB"
              ]
            }
          },
          "product_category": {
            "type": "string",
            "maxLength": 64
          },
          "exposure": {
            "type": "string",
            "enum": [
              "leave_on",
              "rinse_off"
            ],
            "description": "If no product_category"
          },
          "as_of": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "fragrance": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "dose_pct": {
                "type": [
                  "number",
                  "string",
                  "null"
                ],
                "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
              },
              "composition": {
                "type": "array",
                "maxItems": 300,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "inci": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "name": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "cas": {
                      "type": "string",
                      "maxLength": 20
                    },
                    "pct_in_fragrance": {
                      "type": [
                        "number",
                        "string",
                        "null"
                      ],
                      "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                    }
                  }
                }
              }
            }
          },
          "allergens": {
            "type": "array",
            "maxItems": 300,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "inci": {
                  "type": "string",
                  "maxLength": 200
                },
                "name": {
                  "type": "string",
                  "maxLength": 200
                },
                "cas": {
                  "type": "string",
                  "maxLength": 20
                },
                "pct_in_product": {
                  "type": [
                    "number",
                    "string",
                    "null"
                  ],
                  "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                }
              }
            }
          }
        }
      },
      "cosmetics_label_check_body": {
        "type": "object",
        "required": [
          "market",
          "label"
        ],
        "additionalProperties": false,
        "properties": {
          "market": {
            "type": "string",
            "enum": [
              "EU",
              "GB",
              "US",
              "US-CA",
              "US-CO",
              "US-MD",
              "US-ME",
              "US-MN",
              "US-OR",
              "US-VT",
              "US-WA"
            ],
            "description": "EU, GB, US (federal) or a US state (state rules plus US federal)"
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000,
            "description": "Ingredient list as printed, e.g. 'Ingredients: Aqua, Glycerin, ...'"
          },
          "product_category": {
            "type": "string",
            "maxLength": 64
          },
          "as_of": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
            "description": "YYYY-MM-DD"
          },
          "children_under_3": {
            "type": "boolean"
          },
          "formula": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "inci": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "INCI name as on the label"
                },
                "cas": {
                  "type": "string",
                  "pattern": "^\\d{2,7}-\\d{2}-\\d$",
                  "description": "CAS number"
                },
                "ec": {
                  "type": "string",
                  "pattern": "^\\d{3}-\\d{3}-\\d$",
                  "description": "EC (EINECS / ELINCS) number"
                },
                "name": {
                  "type": "string",
                  "maxLength": 200,
                  "description": "Other name (chemical name)"
                },
                "pct": {
                  "type": [
                    "number",
                    "string",
                    "null"
                  ],
                  "description": "Percent w/w (number, or a numeric string). null or omitted = not known: never treated as 0"
                },
                "function": {
                  "type": "string",
                  "maxLength": 40,
                  "description": "What the ingredient does in this formula (e.g. preservative, uv_filter, colorant, ph_adjuster, solvent, denaturant, fragrance_ingredient). Settles entries tied to a use; if omitted they come back NEEDS_ATTENTION."
                },
                "basis": {
                  "type": "string",
                  "maxLength": 60,
                  "description": "Basis of pct when a limit is 'calculated as' something (e.g. 'free base', 'zinc')"
                },
                "intentionally_added": {
                  "type": "boolean",
                  "description": "false for trace/contaminant presence (threshold rules)"
                },
                "flags": {
                  "type": "array",
                  "maxItems": 5,
                  "items": {
                    "type": "string",
                    "enum": [
                      "pfas",
                      "ortho_phthalate",
                      "formaldehyde_releaser"
                    ]
                  },
                  "description": "Class membership you know (class bans cannot be settled from a name)"
                }
              }
            },
            "description": "Concentrations (enables the order and allergen checks)"
          }
        }
      }
    }
  }
}
