{
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "description": "API key (lk_live_..., lk_test_..., or lk_pub_...)",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Pronostico inventory management API - ABC/XYZ classification, demand forecasting, and purchase recommendations.",
    "title": "Pronostico API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/analysis/{jobId}": {
      "get": {
        "parameters": [
          {
            "in": "path",
            "name": "jobId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get analysis job status",
        "tags": [
          "Analysis"
        ],
        "x-required-scope": "pronostico:analysis:read"
      }
    },
    "/api/v1/analysis/{jobId}/results": {
      "get": {
        "description": "Returns complete results (classifications, forecasts, recommendations) for a completed analysis job.",
        "parameters": [
          {
            "in": "path",
            "name": "jobId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get full analysis results",
        "tags": [
          "Analysis"
        ],
        "x-required-scope": "pronostico:analysis:read"
      }
    },
    "/api/v1/analysis/run": {
      "post": {
        "description": "Creates an analysis job using the most recent data upload. The Python engine processes it asynchronously.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "type": {
                    "default": "full",
                    "enum": [
                      "full",
                      "abc_xyz",
                      "forecast",
                      "orders"
                    ],
                    "type": "string"
                  },
                  "upload_id": {
                    "description": "Specific upload to analyze. If omitted, uses latest.",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Start a new analysis",
        "tags": [
          "Analysis"
        ],
        "x-required-scope": "pronostico:analysis:write"
      }
    },
    "/api/v1/classifications": {
      "get": {
        "description": "Each row carries is_inactive (true = no sales in the last 6 months AND zero current stock) and sales_last_6mo. Use ?active=true for active indexes only (matches the app default view), ?active=false for inactive only, or omit for the full catalog.",
        "parameters": [
          {
            "description": "Job ID. Defaults to latest completed.",
            "in": "query",
            "name": "job_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Filter by combined class (e.g., AX, BZ)",
            "in": "query",
            "name": "class",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "true = active indexes only (matches app default), false = inactive only. Omit for all.",
            "in": "query",
            "name": "active",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get ABC/XYZ classifications",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/customers": {
      "get": {
        "description": "Returns tenant-scoped customers ranked by revenue with order statistics.",
        "parameters": [
          {
            "in": "query",
            "name": "classification",
            "schema": {
              "enum": [
                "top",
                "regular",
                "sporadic"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 1000,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List customer rankings",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/customers/{id}": {
      "get": {
        "description": "Returns tenant-scoped customer details and a per-SKU order summary.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_from",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "schema": {
              "format": "date",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get customer details",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/data/models": {
      "post": {
        "description": "Upserts model-level ordering constraints onto the product master: model_id groups symbols that share a model MOQ, units_per_carton rounds orders up to whole cartons, model_moq is the minimum order quantity for the whole model. Each row must set at least one of model_id, units_per_carton, model_moq. The next analysis run applies carton rounding + model-level MOQ.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "model_id": {
                          "type": "string"
                        },
                        "model_moq": {
                          "type": "number"
                        },
                        "sku": {
                          "type": "string"
                        },
                        "units_per_carton": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "sku"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push model grouping + carton size + model MOQ",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/prices": {
      "post": {
        "description": "Stores normalized SKU purchase/sell prices on products as PLN economic master data and optionally updates supplier purchase prices when supplier_name matches an existing supplier.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "currency": {
                          "type": "string"
                        },
                        "purchase_price": {
                          "type": "number"
                        },
                        "sell_price": {
                          "type": "number"
                        },
                        "sku": {
                          "type": "string"
                        },
                        "supplier_name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "sku",
                        "purchase_price"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push product pricing data",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/purchase-orders": {
      "post": {
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "eta": {
                          "format": "date",
                          "type": "string"
                        },
                        "po_number": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "number"
                        },
                        "sku": {
                          "type": "string"
                        },
                        "supplier_name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "sku",
                        "po_number",
                        "quantity",
                        "eta"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push open purchase orders",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/sales": {
      "post": {
        "description": "Push historical sales rows for analysis. For <=5000 rows, processed synchronously. For >5000 rows, returns an async job.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "date": {
                          "format": "date",
                          "type": "string"
                        },
                        "quantity": {
                          "type": "number"
                        },
                        "revenue": {
                          "type": "number"
                        },
                        "sku": {
                          "type": "string"
                        },
                        "supplier_name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "sku",
                        "date",
                        "quantity"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push sales/demand data",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/sales/list": {
      "get": {
        "description": "Returns tenant-scoped, deduplicated sales transaction rows.",
        "parameters": [
          {
            "in": "query",
            "name": "sku",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_from",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "customer_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 1000,
              "maximum": 5000,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List sales transactions",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:read"
      }
    },
    "/api/v1/data/sku-mappings": {
      "post": {
        "description": "Stores mappings from old_sku to new_sku with effective_date. The next analysis run merges historical demand from old references into the new SKU before forecasting.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "effective_date": {
                          "format": "date",
                          "type": "string"
                        },
                        "new_sku": {
                          "type": "string"
                        },
                        "old_sku": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "old_sku",
                        "new_sku",
                        "effective_date"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push SKU reference-change mappings",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/sku-moq": {
      "post": {
        "description": "Sets the minimum order quantity per symbol on the SKU's primary supplier link (sku_suppliers.moq_per_sku). When ordering, the engine and the order-horizon recompute raise the recommended quantity to this MOQ before rounding up to whole cartons. Re-pushing replaces the MOQ for the given SKUs. A primary link is created under the default supplier when a SKU has none. The next analysis run applies the MOQ.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "moq": {
                          "description": "Minimum order quantity. Greater than 0 sets it; 0 clears it (used to hold MOQ on ambiguous multi-size model groups).",
                          "type": "number"
                        },
                        "sku": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "sku",
                        "moq"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push per-SKU minimum order quantity (MOQ)",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/stock": {
      "post": {
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "rows": {
                    "items": {
                      "properties": {
                        "sku": {
                          "type": "string"
                        },
                        "stock_available": {
                          "type": "number"
                        },
                        "stock_reserved": {
                          "type": "number"
                        },
                        "stock_total": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "sku",
                        "stock_total"
                      ],
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "rows"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Push current stock levels",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:write"
      }
    },
    "/api/v1/data/stock/snapshots": {
      "get": {
        "description": "Returns tenant-scoped stock snapshots, optionally reduced to the latest snapshot per SKU.",
        "parameters": [
          {
            "in": "query",
            "name": "sku",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_from",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "date_to",
            "schema": {
              "format": "date",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "latest_only",
            "schema": {
              "enum": [
                "1"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 5000,
              "maximum": 50000,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List stock snapshots",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:read"
      }
    },
    "/api/v1/data/uploads": {
      "get": {
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List data uploads",
        "tags": [
          "Data"
        ],
        "x-required-scope": "pronostico:data:read"
      }
    },
    "/api/v1/forecasts": {
      "get": {
        "description": "Each row carries is_inactive (true = no sales in the last 6 months AND zero current stock, derived from the SKU classification). Use ?active=true for active indexes only (matches the app default view), ?active=false for inactive only, or omit for all.",
        "parameters": [
          {
            "in": "query",
            "name": "job_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "sku",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "true = active indexes only (matches app default), false = inactive only. Omit for all.",
            "in": "query",
            "name": "active",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get demand forecasts",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/health": {
      "get": {
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "app": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [],
        "summary": "Health check",
        "tags": [
          "Health"
        ]
      }
    },
    "/api/v1/recommendations": {
      "get": {
        "description": "Each row carries is_inactive (true = no sales in the last 6 months AND zero current stock, derived from the SKU classification). Use ?active=true for active indexes only (matches the app default view), ?active=false for inactive only, or omit for all.",
        "parameters": [
          {
            "in": "query",
            "name": "job_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "urgency",
            "schema": {
              "enum": [
                "critical",
                "soon",
                "normal",
                "overstock"
              ],
              "type": "string"
            }
          },
          {
            "description": "true = active indexes only (matches app default), false = inactive only. Omit for all.",
            "in": "query",
            "name": "active",
            "schema": {
              "enum": [
                "true",
                "false"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get purchase order recommendations",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/recommendations/export": {
      "get": {
        "description": "Returns flat JSON array of purchase recommendations suitable for ERP system import.",
        "parameters": [
          {
            "in": "query",
            "name": "job_id",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "urgency",
            "schema": {
              "enum": [
                "critical",
                "soon",
                "normal",
                "overstock"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Export recommendations for ERP import",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/sku/{sku}": {
      "get": {
        "description": "Single-call snapshot for a SKU from the latest completed analysis: classification + forecast + recommendation + recent stock snapshots + weekly demand history + customer breakdown + 30/30 customer trend. Lookup accepts either the canonical sku (whatever the tenant maps to it during ingestion — e.g. ANMAR uses Nexo ID) or the supplementary external_ref (e.g. ANMAR's Symbol asortymentu / REF). The response always returns both identifiers when available so consumers can switch gradually.",
        "parameters": [
          {
            "description": "Canonical SKU or external_ref (URL-encoded). ANMAR: Nexo ID.",
            "in": "path",
            "name": "sku",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "analysis_job_id": {
                      "type": "string"
                    },
                    "classification": {
                      "type": "object"
                    },
                    "customer_trend": {
                      "description": "Customer demand trend for this SKU: latest 30 days versus previous 30 days, anchored to the latest sale date in tenant data.",
                      "properties": {
                        "as_of_date": {
                          "format": "date",
                          "nullable": true,
                          "type": "string"
                        },
                        "current_from": {
                          "format": "date",
                          "nullable": true,
                          "type": "string"
                        },
                        "current_order_count": {
                          "type": "integer"
                        },
                        "current_quantity": {
                          "type": "number"
                        },
                        "current_to": {
                          "format": "date",
                          "nullable": true,
                          "type": "string"
                        },
                        "current_unique_customers": {
                          "type": "integer"
                        },
                        "current_value": {
                          "type": "number"
                        },
                        "delta_customers": {
                          "type": "integer"
                        },
                        "delta_pct": {
                          "nullable": true,
                          "type": "number"
                        },
                        "previous_from": {
                          "format": "date",
                          "nullable": true,
                          "type": "string"
                        },
                        "previous_order_count": {
                          "type": "integer"
                        },
                        "previous_quantity": {
                          "type": "number"
                        },
                        "previous_to": {
                          "format": "date",
                          "nullable": true,
                          "type": "string"
                        },
                        "previous_unique_customers": {
                          "type": "integer"
                        },
                        "previous_value": {
                          "type": "number"
                        },
                        "trend": {
                          "enum": [
                            "growing",
                            "stable",
                            "declining",
                            "new",
                            "none"
                          ],
                          "type": "string"
                        },
                        "window_days": {
                          "example": 30,
                          "type": "integer"
                        }
                      },
                      "type": "object"
                    },
                    "customers": {
                      "items": {
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "external_ref": {
                      "description": "Supplementary ERP cross-reference (e.g. REF).",
                      "nullable": true,
                      "type": "string"
                    },
                    "forecast": {
                      "nullable": true,
                      "type": "object"
                    },
                    "history_weekly": {
                      "items": {
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "product_name": {
                      "nullable": true,
                      "type": "string"
                    },
                    "recommendation": {
                      "nullable": true,
                      "type": "object"
                    },
                    "sku": {
                      "description": "Canonical SKU resolved from the request.",
                      "type": "string"
                    },
                    "sku_reference_mappings": {
                      "description": "Reference changes related to this SKU. Used by the dashboard to mark the change point and by analysis runs to merge old history before forecast.",
                      "items": {
                        "properties": {
                          "effective_date": {
                            "format": "date",
                            "type": "string"
                          },
                          "new_sku": {
                            "type": "string"
                          },
                          "old_sku": {
                            "type": "string"
                          },
                          "reason": {
                            "nullable": true,
                            "type": "string"
                          }
                        },
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "stock_snapshots": {
                      "items": {
                        "type": "object"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get full SKU snapshot",
        "tags": [
          "Results"
        ],
        "x-required-scope": "pronostico:results:read"
      }
    },
    "/api/v1/suppliers": {
      "get": {
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "schema": {
              "default": 1,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "per_page",
            "schema": {
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List suppliers",
        "tags": [
          "Suppliers"
        ],
        "x-required-scope": "pronostico:suppliers:read"
      },
      "post": {
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "delivery_days": {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  },
                  "free_transport_above": {
                    "type": "number"
                  },
                  "lead_time_days": {
                    "type": "integer"
                  },
                  "moq_currency": {
                    "type": "string"
                  },
                  "moq_type": {
                    "enum": [
                      "value",
                      "quantity",
                      "weight",
                      "none"
                    ],
                    "type": "string"
                  },
                  "moq_value": {
                    "type": "number"
                  },
                  "name": {
                    "type": "string"
                  },
                  "transport_cost": {
                    "type": "number"
                  },
                  "type": {
                    "enum": [
                      "manufacturer",
                      "distributor"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "type"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Create a supplier",
        "tags": [
          "Suppliers"
        ],
        "x-required-scope": "pronostico:suppliers:write"
      }
    },
    "/api/v1/suppliers/{id}": {
      "delete": {
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Delete a supplier",
        "tags": [
          "Suppliers"
        ],
        "x-required-scope": "pronostico:suppliers:write"
      },
      "get": {
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get supplier details",
        "tags": [
          "Suppliers"
        ],
        "x-required-scope": "pronostico:suppliers:read"
      },
      "patch": {
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key"
          },
          "403": {
            "description": "Forbidden - missing required scope"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "500": {
            "description": "Internal server error"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Update a supplier",
        "tags": [
          "Suppliers"
        ],
        "x-required-scope": "pronostico:suppliers:write"
      }
    }
  },
  "servers": [
    {
      "url": "https://pronostico.locura.tech"
    }
  ]
}
