[
  {
    "path": "GET /api/health",
    "auth": "Public",
    "description": "",
    "params": [],
    "example": "{\n  \"status\": \"ok\",\n  \"database\": \"gfs-netsuite\",\n  \"counts\": {\n    \"customers\": 283, \"vendors\": 484, \"items\": 1265,\n    \"transactions\": 102367, \"invoice_lines\": 28528,\n    \"so_lines\": 29098, \"vb_lines\": 21315, \"pricing\": 1264\n  },\n  \"timestamp\": \"2026-05-19T13:33:03.674Z\"\n}"
  },
  {
    "path": "GET /api/kpis",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{\n  \"revenue_2026_ytd\": 11272175.89,\n  \"revenue_2025_total\": 28435586.26,\n  \"open_ar\": { \"amount\": 2299955.6, \"count\": 216 },\n  \"open_ap\": { \"amount\": ..., \"count\": ... },\n  \"open_so\": { \"amount\": ..., \"count\": 90 },\n  \"timestamp\": \"...\"\n}"
  },
  {
    "path": "GET /api/briefing",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{\n  \"revenue_2026_ytd\": ...,\n  \"open_ar\": { \"amount\": ..., \"count\": ... },\n  \"open_so\": { \"amount\": ..., \"count\": ... },\n  \"invoices_this_month\": { \"amount\": ..., \"count\": ... },\n  \"top_customers_2026\": [ { \"entity_name\": \"Driscoll Foods\", \"revenue\": 4107918.47 }, ... ],\n  \"timestamp\": \"...\"\n}"
  },
  {
    "path": "GET /api/customers",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "q",
        "Type": "string",
        "Default": "\u2014",
        "Description": "Search by company name (LIKE %q%)"
      },
      {
        "Param": "limit",
        "Type": "int",
        "Default": "50",
        "Description": "1-200"
      },
      {
        "Param": "offset",
        "Type": "int",
        "Default": "0",
        "Description": "0-100000"
      }
    ],
    "example": "{ \"items\": [...], \"total\": 283, \"limit\": 50, \"offset\": 0 }"
  },
  {
    "path": "GET /api/customers/:id",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{ \"id\": 475, \"companyname\": \"Jkings\", ..., \"contacts\": [...], \"pricing\": [...], \"recent_orders\": [...] }"
  },
  {
    "path": "GET /api/customers/:id/history",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{ \"customer_id\": \"475\", \"yearly\": [{ \"year\": 2026, \"type\": \"CustInvc\", \"txn_count\": 47, \"total\": ... }], \"top_items\": [...] }"
  },
  {
    "path": "GET /api/customers/ranking",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "year",
        "Type": "int",
        "Default": "2026"
      }
    ],
    "example": "{ \"year\": 2026, \"items\": [{ \"customer\": \"Driscoll Foods\", \"customer_id\": 539, \"inv_count\": ..., \"revenue\": 4107918.47 }, ...] }"
  },
  {
    "path": "GET /api/vendors",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": ""
  },
  {
    "path": "GET /api/vendors/spend",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "year",
        "Type": "int",
        "Default": "2026"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/items",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "type",
        "Type": "string",
        "Default": "\u2014",
        "Allowed Values": "InvtPart, Assembly, Kit, NonInvtPart"
      },
      {
        "Param": "allergen",
        "Type": "string",
        "Default": "\u2014",
        "Allowed Values": "milk, eggs, peanuts, soybeans, wheat, fish, tree_nuts, crustacean, celery, lupin, molluscs, mustard, sesame, sulphur_dioxide"
      },
      {
        "Param": "limit",
        "Type": "int",
        "Default": "50",
        "Allowed Values": "1-200"
      },
      {
        "Param": "offset",
        "Type": "int",
        "Default": "0",
        "Allowed Values": "0-100000"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/items/:id",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": ""
  },
  {
    "path": "GET /api/items/performance",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "year",
        "Type": "int",
        "Default": "2026"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/items/:id/customers",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": ""
  },
  {
    "path": "GET /api/transactions",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "type",
        "Type": "string",
        "Default": "CustInvc",
        "Allowed": "16 validated types"
      },
      {
        "Param": "year",
        "Type": "int",
        "Default": "\u2014",
        "Allowed": "2018-2027"
      },
      {
        "Param": "limit",
        "Type": "int",
        "Default": "50",
        "Allowed": "1-200"
      },
      {
        "Param": "offset",
        "Type": "int",
        "Default": "0",
        "Allowed": "0-100000"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/ar/aging",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{ \"items\": [{ \"customer\": \"...\", \"customer_id\": ..., \"inv_count\": ..., \"total_ar\": ..., \"current_bal\": ..., \"days_1_30\": ..., \"days_31_60\": ..., \"days_61_90\": ..., \"days_90_plus\": ... }] }"
  },
  {
    "path": "GET /api/financials/summary",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": "{ \"revenue\": [{ \"year\": 2026, \"invoices\": 712, \"total\": 11272175.89 }, ...], \"cogs\": [...], \"collections\": [...] }"
  },
  {
    "path": "GET /api/financials/monthly",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "year",
        "Type": "int",
        "Default": "2026"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/revenue/trend",
    "auth": "Bearer",
    "description": "",
    "params": [],
    "example": ""
  },
  {
    "path": "GET /api/gl/accounts",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "type",
        "Type": "string",
        "Default": "\u2014",
        "Values": "Bank, AcctRec, AcctPay, Income, COGS, Expense, Equity, OthCurrAsset, OthCurrLiab, FixedAsset, OthIncome, OthExpense, NonPosting"
      }
    ],
    "example": ""
  },
  {
    "path": "GET /api/search",
    "auth": "Bearer",
    "description": "",
    "params": [
      {
        "Param": "q",
        "Type": "string",
        "Required": "Yes (max 100 chars)"
      }
    ],
    "example": "{ \"results\": [{ \"id\": 475, \"name\": \"Jkings\", \"type\": \"customer\" }, { \"id\": 539, \"name\": \"Driscoll Foods\", \"type\": \"customer\" }, ...] }"
  },
  {
    "path": "GET /api/pricing/derive",
    "auth": "Bearer (admin)",
    "description": "Triggers full re-derivation of customer_pricing_proposed from invoice_lines. Reads up to last 3 invoices per (customer, item) since 2024-01, applies median when 3+ exist, else last_paid. Clears existing 'proposed' rows then inserts the fresh set. Idempotent — running twice produces the same result. Implements ADR-012.",
    "params": [],
    "example": "{\n  \"derived_count\": 661,\n  \"median_last_3\": 445,\n  \"last_paid\": 216,\n  \"invoice_rows_read\": 24560,\n  \"derived_at\": \"2026-05-20T13:30:00.000Z\",\n  \"ms\": 4823\n}"
  },
  {
    "path": "GET /api/pricing/diff",
    "auth": "Bearer",
    "description": "Three-bucket audit across customer_pricing (NS current state) vs customer_pricing_proposed (derived). Listed+Recent = both have rows for the pair → drift check. Listed+Stale = NS has row, derive doesn't → candidate to deprecate. Not-Listed+Recent = derive has row, NS doesn't → orphan items being bought without price-list entry.",
    "params": [
      { "Param": "customer", "Type": "int", "Default": "—", "Description": "Scope to one customer ID" }
    ],
    "example": "{\n  \"summary\": { \"proposed_customers\": 103, \"proposed_rows\": 661 },\n  \"buckets\": {\n    \"listed_recent\":     { \"count\": 434, \"sample\": [...] },\n    \"listed_stale\":      { \"count\": 830, \"sample\": [...] },\n    \"not_listed_recent\": { \"count\": 227, \"sample\": [...] }\n  },\n  \"customer_filter\": null,\n  \"timestamp\": \"...\"\n}"
  },
  {
    "path": "GET /api/pricing/customer/:id",
    "auth": "Bearer",
    "description": "Per-customer pricing view: current NS rows + derived proposed rows + stale rows (in NS but no recent invoice). Each proposed row tagged with bucket (listed_recent / not_listed_recent) and delta_pct vs current.",
    "params": [],
    "example": "{\n  \"customer\": { \"id\": 539, \"name\": \"Driscoll Foods\" },\n  \"current_count\": 42,\n  \"proposed_count\": 88,\n  \"stale_count\": 12,\n  \"proposed\": [\n    { \"item\": 913, \"itemid\": \"PUB5001H ...\", \"derived_price\": 110.40, \"current_price\": 102.00, \"source\": \"median_last_3\", \"invoice_count\": 3, \"bucket\": \"listed_recent\", \"delta_pct\": 8.2 }\n  ],\n  \"stale\": [...],\n  \"current_full\": [...]\n}"
  },
  {
    "path": "GET /api/pricing/audit/summary",
    "auth": "Bearer",
    "description": "High-level pricing audit snapshot: proposed counts, source breakdown (median_last_3 vs last_paid), three-bucket counts, open SOs in flight (would be affected by cutover), last-derived timestamp.",
    "params": [],
    "example": "{\n  \"proposed_customers\": 103,\n  \"proposed_rows\": 661,\n  \"source_breakdown\": [\n    { \"source\": \"last_paid\",     \"cnt\": 216 },\n    { \"source\": \"median_last_3\", \"cnt\": 445 }\n  ],\n  \"buckets\": {\n    \"listed_recent\":     434,\n    \"listed_stale\":      830,\n    \"not_listed_recent\": 227\n  },\n  \"open_sos_in_flight\": { \"count\": 90, \"customers_affected\": 33 },\n  \"last_derived_at\": \"2026-05-20T...\",\n  \"timestamp\": \"...\"\n}"
  }
]