{
  "openapi": "3.0.3",
  "info": {
    "title": "BIX — API pública",
    "version": "1.0.0",
    "description": "API do BIX para fornecedores e serviços de fora. Autenticação por chave (Configuração Global › API), sempre no cabeçalho `Authorization: Bearer <chave>`. Erros em `{\"code\", \"detail\"}`: decida pelo `code`."
  },
  "servers": [
    {
      "url": "https://demonstracao.appbix.com.br/external-api/v1"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Cadastros"
    },
    {
      "name": "Ruptura"
    },
    {
      "name": "Validade"
    },
    {
      "name": "WMS"
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "bix_<prefixo>_<segredo>"
      }
    }
  },
  "paths": {
    "/stores": {
      "get": {
        "operationId": "get-stores",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar lojas",
        "description": "As lojas (e centros de distribuição) do cliente da chave. O `code` é o **código de integração** cadastrado no BIX: é por ele que os outros recursos identificam a loja.\n\nChave restrita a algumas lojas recebe só as lojas dela.\n\nEscopo exigido: `stores.read` (Cadastros · Lojas e grupos (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 12
                          },
                          "code": {
                            "type": "string",
                            "example": "0012"
                          },
                          "name": {
                            "type": "string",
                            "example": "Loja Centro"
                          },
                          "cnpj": {
                            "type": "string",
                            "example": "12345678000190"
                          },
                          "number": {
                            "type": "string",
                            "example": "12"
                          },
                          "kind": {
                            "type": "string",
                            "example": "store"
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 12,
                      "code": "0012",
                      "name": "Loja Centro",
                      "cnpj": "12345678000190",
                      "number": "12",
                      "kind": "store",
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "stores.read"
      }
    },
    "/products": {
      "get": {
        "operationId": "get-products",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar produtos",
        "description": "O cadastro de produtos do cliente. Cada código de barras é um item: o mesmo `internal_code` pode aparecer com vários `ean` (a unidade, a caixa, um EAN alternativo).\n\nOrdem estável por `id`. Para sincronizar, use `updated_since` com `include_inactive=true`.\n\nEscopo exigido: `catalog.read` (Cadastros · Produtos (leitura)).",
        "parameters": [
          {
            "name": "internal_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "ean",
            "in": "query",
            "required": false,
            "description": "Código de barras.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "7891234567890"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "internal_code": {
                            "type": "string",
                            "example": "1001"
                          },
                          "ean": {
                            "type": "string",
                            "example": "7891234567890"
                          },
                          "description": {
                            "type": "string",
                            "example": "ARROZ TIPO 1 5KG"
                          },
                          "unit": {
                            "type": "string",
                            "example": "UN"
                          },
                          "multiplier": {
                            "type": "integer",
                            "example": 1
                          },
                          "price": {
                            "type": "number",
                            "example": 27.9
                          },
                          "category": {
                            "type": "object",
                            "properties": {
                              "n0": {
                                "type": "string",
                                "example": ""
                              },
                              "n1": {
                                "type": "string",
                                "example": "01"
                              },
                              "n2": {
                                "type": "string",
                                "example": "0105"
                              },
                              "n3": {
                                "type": "string",
                                "example": ""
                              },
                              "n4": {
                                "type": "string",
                                "example": ""
                              }
                            }
                          },
                          "reference_code": {
                            "type": "string",
                            "example": ""
                          },
                          "color_code": {
                            "type": "string",
                            "example": ""
                          },
                          "color_description": {
                            "type": "string",
                            "example": ""
                          },
                          "size": {
                            "type": "string",
                            "example": ""
                          },
                          "sales_curve": {
                            "type": "string",
                            "example": "A"
                          },
                          "supplier": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "12345678000190"
                              },
                              "name": {
                                "type": "string",
                                "example": "Fornecedor Exemplo"
                              }
                            }
                          },
                          "buyer": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "07"
                              },
                              "name": {
                                "type": "string",
                                "example": "Comprador Mercearia"
                              }
                            }
                          },
                          "id": {
                            "type": "integer",
                            "example": 345
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "internal_code": "1001",
                      "ean": "7891234567890",
                      "description": "ARROZ TIPO 1 5KG",
                      "unit": "UN",
                      "multiplier": 1,
                      "price": 27.9,
                      "category": {
                        "n0": "",
                        "n1": "01",
                        "n2": "0105",
                        "n3": "",
                        "n4": ""
                      },
                      "reference_code": "",
                      "color_code": "",
                      "color_description": "",
                      "size": "",
                      "sales_curve": "A",
                      "supplier": {
                        "code": "12345678000190",
                        "name": "Fornecedor Exemplo"
                      },
                      "buyer": {
                        "code": "07",
                        "name": "Comprador Mercearia"
                      },
                      "id": 345,
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "catalog.read"
      },
      "post": {
        "operationId": "post-products",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar produtos (criar ou atualizar)",
        "description": "Cria ou atualiza produtos pela chave **(`internal_code`, `ean`)**. Produto que já existe recebe só os campos enviados: o que não vier no item não é alterado. Para tirar um produto de linha, envie `active: false`.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `catalog.write` (Cadastros · Produtos (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 2
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 1
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "updated"
                          },
                          "id": {
                            "type": "integer",
                            "example": 345
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 2,
                    "created": 1,
                    "updated": 1,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "updated",
                      "id": 345,
                      "code": null,
                      "detail": null
                    },
                    {
                      "index": 1,
                      "status": "created",
                      "id": 346,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "internal_code",
                        "ean"
                      ],
                      "properties": {
                        "internal_code": {
                          "type": "string",
                          "description": "Código interno no ERP.",
                          "example": "1001"
                        },
                        "ean": {
                          "type": "string",
                          "description": "Código de barras. Com o `internal_code`, identifica o item.",
                          "example": "7891234567890"
                        },
                        "description": {
                          "type": "string",
                          "description": "Descrição.",
                          "example": "ARROZ TIPO 1 5KG"
                        },
                        "unit": {
                          "type": "string",
                          "description": "Unidade de medida.",
                          "example": "UN"
                        },
                        "multiplier": {
                          "type": "integer",
                          "description": "Quantas unidades este código de barras representa (caixa com 12 = `12`).",
                          "example": 1
                        },
                        "price": {
                          "type": "number",
                          "description": "Preço de cadastro. O preço por loja vai em `POST /stock-prices`.",
                          "example": 27.9
                        },
                        "category": {
                          "type": "object",
                          "properties": {
                            "n0": {
                              "type": "string",
                              "description": "Código do nível N0."
                            },
                            "n1": {
                              "type": "string",
                              "description": "Código do nível N1."
                            },
                            "n2": {
                              "type": "string",
                              "description": "Código do nível N2."
                            },
                            "n3": {
                              "type": "string",
                              "description": "Código do nível N3."
                            },
                            "n4": {
                              "type": "string",
                              "description": "Código do nível N4."
                            }
                          },
                          "description": "Códigos da estrutura mercadológica, nível a nível (os mesmos de `POST /categories`)."
                        },
                        "reference_code": {
                          "type": "string",
                          "description": "Código de referência (informativo)."
                        },
                        "color_code": {
                          "type": "string",
                          "description": "Código da cor (informativo)."
                        },
                        "color_description": {
                          "type": "string",
                          "description": "Descrição da cor (informativo)."
                        },
                        "size": {
                          "type": "string",
                          "description": "Tamanho (informativo)."
                        },
                        "sales_curve": {
                          "type": "string",
                          "description": "Curva de venda da rede (A, B, C...).",
                          "example": "A"
                        },
                        "supplier": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome. Só preenche o cadastro que está sem nome."
                            }
                          },
                          "description": "Fornecedor. Criado se não existir."
                        },
                        "buyer": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome. Só preenche o cadastro que está sem nome."
                            }
                          },
                          "description": "Comprador. Criado se não existir."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "`false` tira o produto de linha; `true` reativa.",
                          "example": true
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "internal_code": "1001",
                    "ean": "7891234567890",
                    "description": "ARROZ TIPO 1 5KG",
                    "unit": "UN",
                    "multiplier": 1,
                    "price": 27.9,
                    "category": {
                      "n0": "",
                      "n1": "01",
                      "n2": "0105",
                      "n3": "",
                      "n4": ""
                    },
                    "sales_curve": "A",
                    "supplier": {
                      "code": "12345678000190",
                      "name": "Fornecedor Exemplo"
                    }
                  },
                  {
                    "internal_code": "1001",
                    "ean": "17891234567897",
                    "description": "ARROZ TIPO 1 5KG CX 6",
                    "unit": "CX",
                    "multiplier": 6
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "catalog.write"
      }
    },
    "/categories": {
      "get": {
        "operationId": "get-categories",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar a estrutura mercadológica",
        "description": "Os ramos da estrutura mercadológica do cliente, em até cinco níveis (`n0` a `n4`, por exemplo Empresa › Departamento › Seção › Grupo › Subgrupo). Cada item é um ramo: a combinação dos códigos dos cinco níveis.\n\nEscopo exigido: `catalog.read` (Cadastros · Produtos (leitura)).",
        "parameters": [
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "n0": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": ""
                              },
                              "name": {
                                "type": "string",
                                "example": ""
                              }
                            }
                          },
                          "n1": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "01"
                              },
                              "name": {
                                "type": "string",
                                "example": "MERCEARIA"
                              }
                            }
                          },
                          "n2": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "0105"
                              },
                              "name": {
                                "type": "string",
                                "example": "ARROZ E FEIJÃO"
                              }
                            }
                          },
                          "n3": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": ""
                              },
                              "name": {
                                "type": "string",
                                "example": ""
                              }
                            }
                          },
                          "n4": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": ""
                              },
                              "name": {
                                "type": "string",
                                "example": ""
                              }
                            }
                          },
                          "id": {
                            "type": "integer",
                            "example": 88
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "n0": {
                        "code": "",
                        "name": ""
                      },
                      "n1": {
                        "code": "01",
                        "name": "MERCEARIA"
                      },
                      "n2": {
                        "code": "0105",
                        "name": "ARROZ E FEIJÃO"
                      },
                      "n3": {
                        "code": "",
                        "name": ""
                      },
                      "n4": {
                        "code": "",
                        "name": ""
                      },
                      "id": 88,
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "catalog.read"
      },
      "post": {
        "operationId": "post-categories",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar a estrutura mercadológica",
        "description": "Cria ou atualiza ramos da estrutura. A chave é a **combinação dos códigos dos cinco níveis**: o mesmo ramo enviado de novo só atualiza os nomes. Nível que não existe no seu ERP pode ser omitido.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `catalog.write` (Cadastros · Produtos (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 2
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 1
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "updated"
                          },
                          "id": {
                            "type": "integer",
                            "example": 88
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 2,
                    "created": 1,
                    "updated": 1,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "updated",
                      "id": 88,
                      "code": null,
                      "detail": null
                    },
                    {
                      "index": 1,
                      "status": "created",
                      "id": 89,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [],
                      "properties": {
                        "n0": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código do nível no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome do nível."
                            }
                          },
                          "description": "Nível N0 do ramo."
                        },
                        "n1": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código do nível no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome do nível."
                            }
                          },
                          "description": "Nível N1 do ramo."
                        },
                        "n2": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código do nível no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome do nível."
                            }
                          },
                          "description": "Nível N2 do ramo."
                        },
                        "n3": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código do nível no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome do nível."
                            }
                          },
                          "description": "Nível N3 do ramo."
                        },
                        "n4": {
                          "type": "object",
                          "properties": {
                            "code": {
                              "type": "string",
                              "description": "Código do nível no ERP."
                            },
                            "name": {
                              "type": "string",
                              "description": "Nome do nível."
                            }
                          },
                          "description": "Nível N4 do ramo."
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "n1": {
                      "code": "01",
                      "name": "MERCEARIA"
                    },
                    "n2": {
                      "code": "0105",
                      "name": "ARROZ E FEIJÃO"
                    }
                  },
                  {
                    "n1": {
                      "code": "01",
                      "name": "MERCEARIA"
                    },
                    "n2": {
                      "code": "0106",
                      "name": "MASSAS"
                    }
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "catalog.write"
      }
    },
    "/stock-prices": {
      "get": {
        "operationId": "get-stock-prices",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar preço e saldo por loja",
        "description": "O preço e o saldo de cada produto em cada loja, como o ERP informou (por depósito, quando o ERP separa). É o saldo do ERP, não o do WMS do BIX: para esse, use `GET /wms/stock-balances`.\n\nOrdem estável por `id`.\n\nEscopo exigido: `stock_prices.read` (Cadastros · Preço e saldo (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "store_id",
            "in": "query",
            "required": false,
            "description": "Id da loja no BIX.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": 12
          },
          {
            "name": "internal_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "ean",
            "in": "query",
            "required": false,
            "description": "Código de barras.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "7891234567890"
          },
          {
            "name": "warehouse",
            "in": "query",
            "required": false,
            "description": "Depósito, como o ERP envia.",
            "schema": {
              "type": "string"
            },
            "example": "01"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 5012
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 345
                              },
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "ARROZ TIPO 1 5KG"
                              }
                            }
                          },
                          "warehouse": {
                            "type": "string",
                            "example": "01"
                          },
                          "balance": {
                            "type": "number",
                            "example": 48.0
                          },
                          "price": {
                            "type": "number",
                            "example": 27.9
                          },
                          "price_regular": {
                            "type": "number",
                            "example": 29.9
                          },
                          "price_offer": {
                            "type": "number",
                            "example": 27.9
                          },
                          "curve": {
                            "type": "string",
                            "example": "A"
                          },
                          "costs": {
                            "type": "object",
                            "properties": {
                              "average_accounting": {
                                "type": "number",
                                "example": 18.4
                              },
                              "average_no_tax": {
                                "type": "number",
                                "example": 16.9
                              },
                              "average_with_tax": {
                                "type": "number",
                                "example": 19.2
                              },
                              "last_purchase_gross": {
                                "type": "number",
                                "example": 20.5
                              },
                              "last_purchase_net": {
                                "type": "number",
                                "example": 17.8
                              }
                            }
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 5012,
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "product": {
                        "id": 345,
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "ARROZ TIPO 1 5KG"
                      },
                      "warehouse": "01",
                      "balance": 48.0,
                      "price": 27.9,
                      "price_regular": 29.9,
                      "price_offer": 27.9,
                      "curve": "A",
                      "costs": {
                        "average_accounting": 18.4,
                        "average_no_tax": 16.9,
                        "average_with_tax": 19.2,
                        "last_purchase_gross": 20.5,
                        "last_purchase_net": 17.8
                      },
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "stock_prices.read"
      },
      "post": {
        "operationId": "post-stock-prices",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar preço e saldo por loja",
        "description": "Cria ou atualiza o preço e o saldo de produtos por loja, pela chave **(loja, produto, depósito)**. É **parcial**: campo ausente não é alterado, então uma carga de preço e outra de saldo não apagam uma à outra.\n\nA loja vem por `store_code` (código de integração) ou `store_id`; o produto, por `ean` ou `internal_code`. Um `internal_code` com vários EANs atualiza todos eles.\n\n`update_only: true` só atualiza o que já existe: sem registro na loja, o item volta `skipped`. Use em carga que não traz preço nem saldo (só a curva, por exemplo), para não criar linha zerada.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `stock_prices.write` (Cadastros · Preço e saldo (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 2
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 1
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 2,
                    "created": 1,
                    "updated": 1,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "code": null,
                      "detail": null
                    },
                    {
                      "index": 1,
                      "status": "updated",
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [],
                      "properties": {
                        "store_code": {
                          "type": "string",
                          "description": "Código de integração da loja. Ou `store_id`.",
                          "example": "0012"
                        },
                        "store_id": {
                          "type": "integer",
                          "description": "Id da loja no BIX. Ou `store_code`."
                        },
                        "ean": {
                          "type": "string",
                          "description": "Código de barras. Ou `internal_code`."
                        },
                        "internal_code": {
                          "type": "string",
                          "description": "Código interno. Ou `ean`.",
                          "example": "1001"
                        },
                        "warehouse": {
                          "type": "string",
                          "description": "Depósito no ERP. Vazio quando o ERP não separa.",
                          "example": "01"
                        },
                        "balance": {
                          "type": "number",
                          "description": "Saldo.",
                          "example": 48
                        },
                        "price": {
                          "type": "number",
                          "description": "Preço de venda praticado.",
                          "example": 27.9
                        },
                        "price_regular": {
                          "type": "number",
                          "description": "Preço regular (sem oferta). Tem prioridade na rebaixa.",
                          "example": 29.9
                        },
                        "price_offer": {
                          "type": "number",
                          "description": "Preço de oferta. `null` encerra a oferta.",
                          "example": 27.9
                        },
                        "curve": {
                          "type": "string",
                          "description": "Curva do produto na loja (até 50 caracteres). Vazio limpa.",
                          "example": "A"
                        },
                        "costs": {
                          "type": "object",
                          "properties": {
                            "average_accounting": {
                              "type": "number",
                              "description": "Custo médio contábil."
                            },
                            "average_no_tax": {
                              "type": "number",
                              "description": "Custo médio sem impostos."
                            },
                            "average_with_tax": {
                              "type": "number",
                              "description": "Custo médio com impostos."
                            },
                            "last_purchase_gross": {
                              "type": "number",
                              "description": "Custo da última compra, bruto."
                            },
                            "last_purchase_net": {
                              "type": "number",
                              "description": "Custo da última compra, líquido."
                            }
                          },
                          "description": "Custos (opcionais)."
                        },
                        "update_only": {
                          "type": "boolean",
                          "description": "Só atualiza registro existente.",
                          "example": false
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "store_code": "0012",
                    "internal_code": "1001",
                    "warehouse": "01",
                    "balance": 48,
                    "price": 27.9,
                    "price_regular": 29.9
                  },
                  {
                    "store_code": "0012",
                    "internal_code": "1001",
                    "warehouse": "01",
                    "curve": "A",
                    "update_only": true
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "stock_prices.write"
      }
    },
    "/suppliers": {
      "get": {
        "operationId": "get-suppliers",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar fornecedores",
        "description": "Os fornecedores do cliente. O `code` é o código do fornecedor no ERP (em geral o CNPJ) e é o mesmo que o produto usa em `supplier.code`.\n\nEscopo exigido: `catalog.read` (Cadastros · Produtos (leitura)).",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": false,
            "description": "Código no ERP.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "12345678000190"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 31
                          },
                          "code": {
                            "type": "string",
                            "example": "12345678000190"
                          },
                          "legal_name": {
                            "type": "string",
                            "example": "FORNECEDOR EXEMPLO LTDA"
                          },
                          "trade_name": {
                            "type": "string",
                            "example": "Exemplo"
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 31,
                      "code": "12345678000190",
                      "legal_name": "FORNECEDOR EXEMPLO LTDA",
                      "trade_name": "Exemplo",
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "catalog.read"
      },
      "post": {
        "operationId": "post-suppliers",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar fornecedores",
        "description": "Cria ou atualiza fornecedores pelo `code`. Aqui o ERP é a fonte: o nome enviado substitui o que está no BIX. Campo ausente não é alterado.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `catalog.write` (Cadastros · Produtos (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 1
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "id": {
                            "type": "integer",
                            "example": 31
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 1,
                    "created": 1,
                    "updated": 0,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "id": 31,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "code"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Código do fornecedor no ERP (em geral o CNPJ).",
                          "example": "12345678000190"
                        },
                        "legal_name": {
                          "type": "string",
                          "description": "Razão social.",
                          "example": "FORNECEDOR EXEMPLO LTDA"
                        },
                        "trade_name": {
                          "type": "string",
                          "description": "Nome fantasia.",
                          "example": "Exemplo"
                        },
                        "active": {
                          "type": "boolean",
                          "description": "`false` desativa.",
                          "example": true
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "code": "12345678000190",
                    "legal_name": "FORNECEDOR EXEMPLO LTDA",
                    "trade_name": "Exemplo"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "catalog.write"
      }
    },
    "/buyers": {
      "get": {
        "operationId": "get-buyers",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar compradores",
        "description": "Os compradores do cliente. O `code` é o mesmo que o produto usa em `buyer.code`.\n\nEscopo exigido: `catalog.read` (Cadastros · Produtos (leitura)).",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "required": false,
            "description": "Código do comprador no ERP.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "07"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 7
                          },
                          "code": {
                            "type": "string",
                            "example": "07"
                          },
                          "name": {
                            "type": "string",
                            "example": "COMPRADOR MERCEARIA"
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 7,
                      "code": "07",
                      "name": "COMPRADOR MERCEARIA",
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "catalog.read"
      },
      "post": {
        "operationId": "post-buyers",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar compradores",
        "description": "Cria ou atualiza compradores pelo `code`. O nome enviado substitui o que está no BIX.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `catalog.write` (Cadastros · Produtos (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 1
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "id": {
                            "type": "integer",
                            "example": 31
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 1,
                    "created": 1,
                    "updated": 0,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "id": 31,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "code"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Código do comprador no ERP.",
                          "example": "07"
                        },
                        "name": {
                          "type": "string",
                          "description": "Nome.",
                          "example": "COMPRADOR MERCEARIA"
                        },
                        "active": {
                          "type": "boolean",
                          "description": "`false` desativa.",
                          "example": true
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "code": "07",
                    "name": "COMPRADOR MERCEARIA"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "catalog.write"
      }
    },
    "/store-groups": {
      "get": {
        "operationId": "get-store-groups",
        "tags": [
          "Cadastros"
        ],
        "summary": "Listar grupos de lojas",
        "description": "Os grupos de lojas do cliente (regional, bandeira, cluster), usados para agendar tarefas e filtrar relatórios por um conjunto de lojas.\n\nEscopo exigido: `stores.read` (Cadastros · Lojas e grupos (leitura)).",
        "parameters": [
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 4
                          },
                          "name": {
                            "type": "string",
                            "example": "REGIONAL SUL"
                          },
                          "description": {
                            "type": "string",
                            "example": "Lojas do RS e SC"
                          },
                          "stores": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "example": 12
                                },
                                "code": {
                                  "type": "string",
                                  "example": "0012"
                                },
                                "name": {
                                  "type": "string",
                                  "example": "Loja Centro"
                                }
                              }
                            }
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 4,
                      "name": "REGIONAL SUL",
                      "description": "Lojas do RS e SC",
                      "stores": [
                        {
                          "id": 12,
                          "code": "0012",
                          "name": "Loja Centro"
                        }
                      ],
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "stores.read"
      },
      "post": {
        "operationId": "post-store-groups",
        "tags": [
          "Cadastros"
        ],
        "summary": "Enviar grupos de lojas",
        "description": "Cria ou atualiza grupos pelo **nome** (sem diferenciar maiúsculas). `stores`, quando enviado, **substitui** as lojas do grupo: mande a lista completa.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `store_groups.write` (Cadastros · Grupos de lojas (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 1
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "id": {
                            "type": "integer",
                            "example": 31
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 1,
                    "created": 1,
                    "updated": 0,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "id": 31,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "name"
                      ],
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Nome do grupo (é a chave).",
                          "example": "REGIONAL SUL"
                        },
                        "description": {
                          "type": "string",
                          "description": "Descrição.",
                          "example": "Lojas do RS e SC"
                        },
                        "stores": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Códigos de integração das lojas do grupo (lista completa).",
                          "example": [
                            "0012",
                            "0020"
                          ]
                        },
                        "active": {
                          "type": "boolean",
                          "description": "`false` desativa.",
                          "example": true
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "name": "REGIONAL SUL",
                    "description": "Lojas do RS e SC",
                    "stores": [
                      "0012",
                      "0020"
                    ]
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "store_groups.write"
      }
    },
    "/sales/daily": {
      "post": {
        "operationId": "post-sales-daily",
        "tags": [
          "Ruptura"
        ],
        "summary": "Enviar a venda",
        "description": "A venda de **um dia de uma loja** até o momento do envio, agregada por código de barras, no contrato `bix.sales.daily/v1`. É a base da **ruptura por não venda** e encerra a **rebaixa** quando o lote rebaixado é vendido.\n\nEnvie na frequência que puder: em tempo real (o ideal), a cada intervalo ou uma vez ao dia. Em todas, mande o **acumulado do dia** com `complete: true` e o `profiles`: cada envio substitui o anterior do dia e a ruptura provável é recalculada na hora.\n\n- `complete: true` (padrão) **substitui** a venda daquele dia, loja e `source`: reenviar o mesmo lote não duplica, e um lote corrigido corrige.\n- `complete: false` só soma as linhas enviadas, sem substituir o dia; grava a venda, mas **não recalcula a ruptura**.\n- `profiles` traz o perfil do dia de cada produto (venda por hora e intervalos sem venda). **Sem ele, a ruptura por não venda não é avaliada.**\n- Até 50.000 linhas por lote. Linha inválida é recusada sozinha (`rejected`), e o resto grava.\n\nSem cupom, cliente ou CPF: só a venda agregada.\n\nEscopo exigido: `sales.write` (Ruptura · Venda (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "saved": {
                      "type": "integer",
                      "example": 1
                    },
                    "deleted": {
                      "type": "integer",
                      "example": 0
                    },
                    "rejected": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 3
                          },
                          "error": {
                            "type": "string",
                            "example": "quantity inválido"
                          }
                        }
                      }
                    },
                    "profiles": {
                      "type": "integer",
                      "example": 1
                    },
                    "sale_date": {
                      "type": "string",
                      "example": "2026-11-09"
                    },
                    "source": {
                      "type": "string",
                      "example": "erp"
                    },
                    "complete": {
                      "type": "boolean",
                      "example": true
                    },
                    "store": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "example": 12
                        },
                        "code": {
                          "type": "string",
                          "example": "0012"
                        },
                        "name": {
                          "type": "string",
                          "example": "Loja Centro"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "saved": 1,
                  "deleted": 0,
                  "rejected": [
                    {
                      "index": 3,
                      "error": "quantity inválido"
                    }
                  ],
                  "profiles": 1,
                  "sale_date": "2026-11-09",
                  "source": "erp",
                  "complete": true,
                  "store": {
                    "id": 12,
                    "code": "0012",
                    "name": "Loja Centro"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "schema",
                  "source",
                  "sale_date",
                  "location",
                  "rows"
                ],
                "properties": {
                  "schema": {
                    "type": "string",
                    "description": "Sempre `bix.sales.daily/v1`.",
                    "example": "bix.sales.daily/v1"
                  },
                  "source": {
                    "type": "string",
                    "description": "Quem envia: minúsculas, números e `_`, de 2 a 30 (ex.: `erp`). A substituição do `complete` é por fonte.",
                    "example": "erp"
                  },
                  "sale_date": {
                    "type": "string",
                    "description": "O dia da venda (AAAA-MM-DD).",
                    "example": "2026-11-09"
                  },
                  "location": {
                    "type": "object",
                    "properties": {
                      "integration_code": {
                        "type": "string",
                        "description": "Código de integração.",
                        "example": "0012"
                      },
                      "id": {
                        "type": "integer",
                        "description": "Id da loja no BIX."
                      },
                      "cnpj": {
                        "type": "string",
                        "description": "CNPJ da loja."
                      }
                    },
                    "description": "A loja: um destes campos."
                  },
                  "complete": {
                    "type": "boolean",
                    "description": "`true` (padrão) substitui o dia; `false` só soma as linhas.",
                    "example": true
                  },
                  "source_ref": {
                    "type": "string",
                    "description": "Referência sua do lote (arquivo, execução), para rastreio."
                  },
                  "rows": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    },
                    "description": "Uma linha por código de barras e oferta: `product_code`, `gtin`, `on_offer`, `quantity`, `amount`, `full_price_amount`, `receipts` (cupons), `first_sale_at` e `last_sale_at` (HH:MM)."
                  },
                  "profiles": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    },
                    "description": "Perfil do dia por código interno: `hourly_qty` e `hourly_receipts` (24 posições, da 0h às 23h), `sale_moments`, `median_gap_minutes`, `max_gap_minutes`, `max_gap_start`, `max_gap_end`, `store_open_at`, `store_close_at`."
                  }
                }
              },
              "example": {
                "schema": "bix.sales.daily/v1",
                "source": "erp",
                "sale_date": "2026-11-09",
                "location": {
                  "integration_code": "0012"
                },
                "complete": true,
                "rows": [
                  {
                    "product_code": "1001",
                    "gtin": "7891234567890",
                    "on_offer": false,
                    "quantity": 44,
                    "amount": 1227.6,
                    "full_price_amount": 1227.6,
                    "receipts": 39,
                    "first_sale_at": "08:12",
                    "last_sale_at": "21:40"
                  }
                ],
                "profiles": [
                  {
                    "product_code": "1001",
                    "quantity": 44,
                    "receipts": 39,
                    "hourly_qty": [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      2,
                      3,
                      4,
                      5,
                      3,
                      2,
                      3,
                      4,
                      5,
                      6,
                      4,
                      2,
                      1,
                      0,
                      0,
                      0
                    ],
                    "hourly_receipts": [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      2,
                      3,
                      4,
                      5,
                      3,
                      2,
                      3,
                      4,
                      5,
                      6,
                      4,
                      2,
                      1,
                      0,
                      0,
                      0
                    ],
                    "sale_moments": 39,
                    "median_gap_minutes": 18,
                    "max_gap_minutes": 95,
                    "max_gap_start": "14:10",
                    "max_gap_end": "15:45",
                    "store_open_at": "07:02",
                    "store_close_at": "21:55"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "sales.write"
      }
    },
    "/rupture/items": {
      "get": {
        "operationId": "get-rupture-items",
        "tags": [
          "Ruptura"
        ],
        "summary": "Itens auditados",
        "description": "Cada produto das tarefas de ruptura e o que a loja encontrou na gôndola: `rupture` (faltava), `no_rupture` (estava lá), `other` ou `not_here` (o produto não fica mais naquele lugar). Item ainda não auditado vem com `answer: null`.\n\nTraz também o saldo da loja e do CD **congelados quando a tarefa nasceu**, o motivo que o app mostrou, a origem da falta (`operacional`, `logistica`, `comercial`) e quando o produto foi reposto. Use `updated_since` para sincronizar.\n\nEscopo exigido: `rupture.read` (Ruptura · Rupturas (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "answer",
            "in": "query",
            "required": false,
            "description": "`rupture`, `no_rupture`, `other` ou `not_here`.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "rupture"
          },
          {
            "name": "task_id",
            "in": "query",
            "required": false,
            "description": "Id da tarefa.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": 9120
          },
          {
            "name": "answered_since",
            "in": "query",
            "required": false,
            "description": "Respondidos a partir desta data/hora.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T00:00:00-03:00"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 77120
                          },
                          "task": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 9120
                              },
                              "status": {
                                "type": "string",
                                "example": "finalizado"
                              },
                              "date": {
                                "type": "string",
                                "example": "2026-11-10"
                              }
                            }
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "description": {
                                "type": "string",
                                "example": "ARROZ TIPO 1 5KG"
                              }
                            }
                          },
                          "triggers": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "example": "sales"
                            }
                          },
                          "reason": {
                            "type": "string",
                            "example": "Sem venda desde 14:10 (normal: a cada 18 min)"
                          },
                          "curve": {
                            "type": "string",
                            "example": "A"
                          },
                          "store_qty": {
                            "type": "number",
                            "example": 48.0
                          },
                          "cd_qty": {
                            "type": "number",
                            "example": 600.0
                          },
                          "unit_price": {
                            "type": "number",
                            "example": 27.9
                          },
                          "answer": {
                            "type": "string",
                            "example": "rupture"
                          },
                          "rupture_origin": {
                            "type": "string",
                            "example": "operacional"
                          },
                          "answered_at": {
                            "type": "string",
                            "example": "2026-11-10T16:02:00-03:00"
                          },
                          "found_at": {
                            "type": "string",
                            "example": "05-003-02"
                          },
                          "replenished_at": {
                            "type": "string",
                            "example": "2026-11-10T16:40:00-03:00"
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T16:40:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 77120,
                      "task": {
                        "id": 9120,
                        "status": "finalizado",
                        "date": "2026-11-10"
                      },
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "product": {
                        "internal_code": "1001",
                        "description": "ARROZ TIPO 1 5KG"
                      },
                      "triggers": [
                        "sales"
                      ],
                      "reason": "Sem venda desde 14:10 (normal: a cada 18 min)",
                      "curve": "A",
                      "store_qty": 48.0,
                      "cd_qty": 600.0,
                      "unit_price": 27.9,
                      "answer": "rupture",
                      "rupture_origin": "operacional",
                      "answered_at": "2026-11-10T16:02:00-03:00",
                      "found_at": "05-003-02",
                      "replenished_at": "2026-11-10T16:40:00-03:00",
                      "updated_at": "2026-11-10T16:40:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "rupture.read"
      }
    },
    "/rupture/signals": {
      "get": {
        "operationId": "get-rupture-signals",
        "tags": [
          "Ruptura"
        ],
        "summary": "Rupturas prováveis",
        "description": "O que a venda aponta como ruptura provável, antes de alguém ir à gôndola: `gap` (o produto parou de vender por muito mais tempo que o normal no dia) ou `no_sale` (dias seguidos sem venda, improváveis para o giro dele). `stock_qty` é o saldo da loja no fim do dia: positivo indica **ruptura de gôndola** (há estoque, mas não está saindo).\n\nQuando alguém confere na loja, `check_result` diz o que achou: `exposed`, `not_exposed` ou `other`.\n\nEscopo exigido: `rupture.read` (Ruptura · Rupturas (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "sale_date_from",
            "in": "query",
            "required": false,
            "description": "Dia avaliado a partir de (AAAA-MM-DD).",
            "schema": {
              "type": "string"
            },
            "example": "2026-11-01"
          },
          {
            "name": "sale_date_to",
            "in": "query",
            "required": false,
            "description": "Dia avaliado até (AAAA-MM-DD).",
            "schema": {
              "type": "string"
            },
            "example": "2026-11-09"
          },
          {
            "name": "rule",
            "in": "query",
            "required": false,
            "description": "`gap` ou `no_sale`.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "gap"
          },
          {
            "name": "checked",
            "in": "query",
            "required": false,
            "description": "`true`: só os conferidos; `false`: só os não conferidos.",
            "schema": {
              "type": "boolean"
            },
            "example": false
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 3301
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "product_code": {
                            "type": "string",
                            "example": "1001"
                          },
                          "sale_date": {
                            "type": "string",
                            "example": "2026-11-09"
                          },
                          "rule": {
                            "type": "string",
                            "example": "gap"
                          },
                          "gap_start": {
                            "type": "string",
                            "example": "14:10"
                          },
                          "gap_end": {
                            "type": "string",
                            "example": "21:40"
                          },
                          "gap_minutes": {
                            "type": "integer",
                            "example": 450
                          },
                          "baseline_minutes": {
                            "type": "integer",
                            "example": 18
                          },
                          "days_without_sale": {
                            "nullable": true
                          },
                          "expected_days": {
                            "nullable": true
                          },
                          "last_sale_date": {
                            "type": "string",
                            "example": "2026-11-09"
                          },
                          "stock_qty": {
                            "type": "number",
                            "example": 48.0
                          },
                          "checked_at": {
                            "nullable": true
                          },
                          "check_result": {
                            "nullable": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T06:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 3301,
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "product_code": "1001",
                      "sale_date": "2026-11-09",
                      "rule": "gap",
                      "gap_start": "14:10",
                      "gap_end": "21:40",
                      "gap_minutes": 450,
                      "baseline_minutes": 18,
                      "days_without_sale": null,
                      "expected_days": null,
                      "last_sale_date": "2026-11-09",
                      "stock_qty": 48.0,
                      "checked_at": null,
                      "check_result": null,
                      "updated_at": "2026-11-10T06:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "rupture.read"
      }
    },
    "/expiries": {
      "get": {
        "operationId": "get-expiries",
        "tags": [
          "Validade"
        ],
        "summary": "Listar validades",
        "description": "As validades por loja e produto, com a cor do alerta (`red`, `yellow`, `green`) que a regra do cliente dá para os dias que faltam. Vêm de qualquer origem: o ERP, o app (coleta e auditoria) e a importação de planilha.\n\nOrdem estável por `id`. Para sincronizar, use `updated_since` com `include_inactive=true`: a validade é desativada quando o lote acaba (contagem zero ou vendido na rebaixa).\n\nEscopo exigido: `expiry.read` (Validade · Validades (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "product_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "ean",
            "in": "query",
            "required": false,
            "description": "Código de barras.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "7891234567890"
          },
          {
            "name": "alert",
            "in": "query",
            "required": false,
            "description": "Cor do alerta: `red`, `yellow` ou `green`.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "red"
          },
          {
            "name": "expiry_from",
            "in": "query",
            "required": false,
            "description": "Vencimento a partir de (AAAA-MM-DD).",
            "schema": {
              "type": "string"
            },
            "example": "2026-11-10"
          },
          {
            "name": "expiry_to",
            "in": "query",
            "required": false,
            "description": "Vencimento até (AAAA-MM-DD).",
            "schema": {
              "type": "string"
            },
            "example": "2026-12-31"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 7731
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 345
                              },
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "IOGURTE NATURAL 170G"
                              }
                            }
                          },
                          "expiry_date": {
                            "type": "string",
                            "example": "2026-11-20"
                          },
                          "days_to_expire": {
                            "type": "integer",
                            "example": 10
                          },
                          "alert": {
                            "type": "string",
                            "example": "yellow"
                          },
                          "quantity": {
                            "type": "number",
                            "example": 36.0
                          },
                          "batch": {
                            "type": "string",
                            "example": "L2611"
                          },
                          "source": {
                            "type": "string",
                            "example": "ERP"
                          },
                          "audit_status": {
                            "type": "string",
                            "example": "naoiniciado"
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 7731,
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "product": {
                        "id": 345,
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "IOGURTE NATURAL 170G"
                      },
                      "expiry_date": "2026-11-20",
                      "days_to_expire": 10,
                      "alert": "yellow",
                      "quantity": 36.0,
                      "batch": "L2611",
                      "source": "ERP",
                      "audit_status": "naoiniciado",
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "expiry.read"
      },
      "post": {
        "operationId": "post-expiries",
        "tags": [
          "Validade"
        ],
        "summary": "Enviar validades",
        "description": "Envia as validades que o ERP conhece (o lote que chegou com a data de validade, por loja). É a mesma ingestão usada pelas integrações de ERP do BIX.\n\n- **Só insere**: a validade que já existe para a loja, o produto e a data não é alterada (volta `skipped`). Quantidade e baixa do lote ficam com a operação na loja.\n- Lotes do mesmo produto, loja e data no mesmo envio são **somados** num registro só.\n- O produto precisa estar no cadastro do BIX.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `expiry.write` (Validade · Validades (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 1
                        },
                        "created": {
                          "type": "integer",
                          "example": 1
                        },
                        "updated": {
                          "type": "integer",
                          "example": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 1,
                    "created": 1,
                    "updated": 0,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "expiry_date"
                      ],
                      "properties": {
                        "store_code": {
                          "type": "string",
                          "description": "Código de integração da loja. Ou `store_id`.",
                          "example": "0012"
                        },
                        "store_id": {
                          "type": "integer",
                          "description": "Id da loja no BIX. Ou `store_code`."
                        },
                        "internal_code": {
                          "type": "string",
                          "description": "Código interno. Ou `ean`.",
                          "example": "1001"
                        },
                        "ean": {
                          "type": "string",
                          "description": "Código de barras. Ou `internal_code`."
                        },
                        "expiry_date": {
                          "type": "string",
                          "description": "Data de validade: AAAA-MM-DD (também aceita DD/MM/AAAA).",
                          "example": "2026-11-20"
                        },
                        "quantity": {
                          "type": "number",
                          "description": "Quantidade do lote. Padrão 1.",
                          "example": 36
                        },
                        "batch": {
                          "type": "string",
                          "description": "Lote.",
                          "example": "L2611"
                        },
                        "entry_date": {
                          "type": "string",
                          "description": "Data de entrada do lote na loja (AAAA-MM-DD).",
                          "example": "2026-11-03"
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "store_code": "0012",
                    "internal_code": "1001",
                    "expiry_date": "2026-11-20",
                    "quantity": 36,
                    "batch": "L2611",
                    "entry_date": "2026-11-03"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "expiry.write"
      }
    },
    "/markdowns": {
      "get": {
        "operationId": "get-markdowns",
        "tags": [
          "Validade"
        ],
        "summary": "Listar rebaixas",
        "description": "As rebaixas de preço por validade que o BIX calculou, no formato padrão do BIX para publicar rebaixa em um ERP (contrato `bix.markdown.publication/v1`): o bloco `markdown` traz o percentual, o preço cheio, o preço rebaixado e a **vigência** (`starts_on` a `ends_on`), e `store` e `product` dizem onde e o quê.\n\nPara o seu ERP criar a promoção: busque as que estão em `aguardando_pdv` (etiqueta já impressa) e as `encerrada` (a promoção precisa sair), aplique, e confirme em `POST /markdowns/publications`. Use `updated_since` para buscar só o que mudou.\n\nEscopo exigido: `markdown.read` (Validade · Rebaixas (leitura)).",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Situação: `aguardando_aprovacao`, `recusada`, `aguardando_impressao`, `aguardando_pdv`, `ativa` ou `encerrada`.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "aguardando_pdv"
          },
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 4410
                          },
                          "status": {
                            "type": "string",
                            "example": "aguardando_pdv"
                          },
                          "publication_status": {
                            "type": "string",
                            "example": "nao_se_aplica"
                          },
                          "schema": {
                            "type": "string",
                            "example": "bix.markdown.publication/v1"
                          },
                          "markdown": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 4410
                              },
                              "color": {
                                "type": "string",
                                "example": "yellow"
                              },
                              "percent": {
                                "type": "number",
                                "example": 30.0
                              },
                              "full_price": {
                                "type": "number",
                                "example": 7.49
                              },
                              "reduced_price": {
                                "type": "number",
                                "example": 5.24
                              },
                              "quantity": {
                                "type": "number",
                                "example": 18.0
                              },
                              "measurement": {
                                "type": "string",
                                "example": "UN"
                              },
                              "starts_on": {
                                "type": "string",
                                "example": "2026-11-10"
                              },
                              "ends_on": {
                                "type": "string",
                                "example": "2026-11-16"
                              },
                              "expiry_date": {
                                "type": "string",
                                "example": "2026-11-20"
                              },
                              "close_reason": {
                                "nullable": true
                              }
                            }
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              },
                              "cnpj": {
                                "type": "string",
                                "example": "12345678000190"
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "IOGURTE NATURAL 170G"
                              }
                            }
                          },
                          "external": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": ""
                              }
                            }
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 4410,
                      "status": "aguardando_pdv",
                      "publication_status": "nao_se_aplica",
                      "schema": "bix.markdown.publication/v1",
                      "markdown": {
                        "id": 4410,
                        "color": "yellow",
                        "percent": 30.0,
                        "full_price": 7.49,
                        "reduced_price": 5.24,
                        "quantity": 18.0,
                        "measurement": "UN",
                        "starts_on": "2026-11-10",
                        "ends_on": "2026-11-16",
                        "expiry_date": "2026-11-20",
                        "close_reason": null
                      },
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro",
                        "cnpj": "12345678000190"
                      },
                      "product": {
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "IOGURTE NATURAL 170G"
                      },
                      "external": {
                        "code": ""
                      },
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "markdown.read"
      }
    },
    "/markdowns/publications": {
      "post": {
        "operationId": "post-markdowns-publications",
        "tags": [
          "Validade"
        ],
        "summary": "Confirmar a rebaixa no PDV",
        "description": "O retorno do seu ERP para cada rebaixa:\n\n- `applied`: a promoção entrou no PDV. A rebaixa em `aguardando_pdv` passa a `ativa`, como no botão \"Aplicado no PDV\" do Painel de Rebaixas do BIX; `publication_status` vira `publicada`.\n- `error`: o ERP não conseguiu aplicar. `publication_status` vira `erro` e a mensagem fica registrada para a operação.\n- `removed`: a promoção de uma rebaixa encerrada saiu do PDV. `publication_status` vira `encerrada_erp`.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `markdown.write` (Validade · Rebaixas (confirmação)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 1
                        },
                        "created": {
                          "type": "integer",
                          "example": 0
                        },
                        "updated": {
                          "type": "integer",
                          "example": 1
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "updated"
                          },
                          "id": {
                            "type": "integer",
                            "example": 4410
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 1,
                    "created": 0,
                    "updated": 1,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "updated",
                      "id": 4410,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Rota inexistente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "not_found",
                  "detail": "Rota inexistente."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "markdown_id",
                        "result"
                      ],
                      "properties": {
                        "markdown_id": {
                          "type": "integer",
                          "description": "O `id` da rebaixa (de `GET /markdowns`).",
                          "example": 4410
                        },
                        "result": {
                          "type": "string",
                          "description": "`applied`, `error` ou `removed`.",
                          "example": "applied"
                        },
                        "external_code": {
                          "type": "string",
                          "description": "Código da promoção no ERP (até 100 caracteres).",
                          "example": "PROMO-77812"
                        },
                        "message": {
                          "type": "string",
                          "description": "Mensagem do ERP, principalmente no `error` (até 500 caracteres)."
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "markdown_id": 4410,
                    "result": "applied",
                    "external_code": "PROMO-77812"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "markdown.write"
      }
    },
    "/wms/stock-balances": {
      "get": {
        "operationId": "get-wms-stock-balances",
        "tags": [
          "WMS"
        ],
        "summary": "Saldo atual por loja e produto",
        "description": "Saldo atual do WMS, somando todos os depósitos e endereços de cada loja. Cada item de `data` é um par (loja, produto). Filtrando uma loja, cada página traz até `page_size` produtos dela.\n\nO produto é o **item de estoque** do WMS: `product_code` e `ean` aceitam qualquer código do cadastro (a caixa, um EAN alternativo) e chegam ao item que guarda o saldo.\n\nOrdem estável (loja, depois produto): dá para percorrer as páginas sem repetir nem pular linha. Para sincronizar, use `updated_since` com a data da última leitura.\n\nEscopo exigido: `wms.stock.read` (WMS · Saldo (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja (o mesmo do ERP).",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "store_id",
            "in": "query",
            "required": false,
            "description": "Id da loja no BIX.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": 12
          },
          {
            "name": "product_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "ean",
            "in": "query",
            "required": false,
            "description": "Código de barras (EAN) do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "7891234567890"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só pares (loja, produto) cujo saldo mudou a partir desta data/hora (ISO 8601). Data sem hora vale desde 00:00, no fuso de Brasília.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-09T10:00:00-03:00"
          },
          {
            "name": "include_zero",
            "in": "query",
            "required": false,
            "description": "Inclui pares com saldo zero (o WMS guarda a linha zerada com a data da última contagem).",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 345
                              },
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "ARROZ TIPO 1 5KG"
                              },
                              "unit": {
                                "type": "string",
                                "example": "UN"
                              }
                            }
                          },
                          "quantity_total": {
                            "type": "number",
                            "example": 120.0
                          },
                          "quantity_available": {
                            "type": "number",
                            "example": 100.0
                          },
                          "quantity_unavailable": {
                            "type": "number",
                            "example": 20.0
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-09T10:15:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1234
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 25
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": true
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "product": {
                        "id": 345,
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "ARROZ TIPO 1 5KG",
                        "unit": "UN"
                      },
                      "quantity_total": 120.0,
                      "quantity_available": 100.0,
                      "quantity_unavailable": 20.0,
                      "updated_at": "2026-11-09T10:15:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1234,
                    "total_pages": 25,
                    "has_next": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.stock.read"
      }
    },
    "/wms/bin-stocks": {
      "get": {
        "operationId": "get-wms-bin-stocks",
        "tags": [
          "WMS"
        ],
        "summary": "Saldo por endereço",
        "description": "O saldo em cada endereço, por produto, lote, validade e situação: o detalhe que `GET /wms/stock-balances` soma por loja. Use para saber **onde** está o estoque.\n\nO produto é o item de estoque do WMS (ver o guia de WMS). Ordem estável por `id`.\n\nEscopo exigido: `wms.stock.read` (WMS · Saldo (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "storage_location",
            "in": "query",
            "required": false,
            "description": "Código do depósito no WMS.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "01"
          },
          {
            "name": "product_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "ean",
            "in": "query",
            "required": false,
            "description": "Código de barras do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "7891234567890"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_zero",
            "in": "query",
            "required": false,
            "description": "Inclui endereços com saldo zero (guardam a data da última contagem).",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 9021
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "storage_location": {
                            "type": "string",
                            "example": "01"
                          },
                          "bin": {
                            "type": "string",
                            "example": "05-003-02"
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 345
                              },
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "ARROZ TIPO 1 5KG"
                              },
                              "unit": {
                                "type": "string",
                                "example": "UN"
                              }
                            }
                          },
                          "batch": {
                            "type": "string",
                            "example": "L2611"
                          },
                          "expiry_date": {
                            "type": "string",
                            "example": "2027-03-31"
                          },
                          "stock_status": {
                            "type": "string",
                            "example": "available"
                          },
                          "quantity": {
                            "type": "number",
                            "example": 24.0
                          },
                          "last_counted_at": {
                            "type": "string",
                            "example": "2026-11-08T14:20:00-03:00"
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 9021,
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "storage_location": "01",
                      "bin": "05-003-02",
                      "product": {
                        "id": 345,
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "ARROZ TIPO 1 5KG",
                        "unit": "UN"
                      },
                      "batch": "L2611",
                      "expiry_date": "2027-03-31",
                      "stock_status": "available",
                      "quantity": 24.0,
                      "last_counted_at": "2026-11-08T14:20:00-03:00",
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.stock.read"
      }
    },
    "/wms/storage-locations": {
      "get": {
        "operationId": "get-wms-storage-locations",
        "tags": [
          "WMS"
        ],
        "summary": "Listar depósitos",
        "description": "Os depósitos do WMS em cada loja (estoque da loja, depósito, avaria...). O `code` é o que as movimentações usam em `storage_location`; o `erp_code` é o código do mesmo depósito no ERP, quando ele existe lá.\n\n`type.counts_as_available` diz se o saldo do depósito conta como disponível (avaria e trânsito, por exemplo, não contam).\n\nEscopo exigido: `wms.structure.read` (WMS · Estrutura (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 3
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "code": {
                            "type": "string",
                            "example": "01"
                          },
                          "name": {
                            "type": "string",
                            "example": "Loja"
                          },
                          "erp_code": {
                            "type": "string",
                            "example": "01"
                          },
                          "type": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "LOJA"
                              },
                              "name": {
                                "type": "string",
                                "example": "Estoque da loja"
                              },
                              "counts_as_available": {
                                "type": "boolean",
                                "example": true
                              }
                            }
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 3,
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "code": "01",
                      "name": "Loja",
                      "erp_code": "01",
                      "type": {
                        "code": "LOJA",
                        "name": "Estoque da loja",
                        "counts_as_available": true
                      },
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.structure.read"
      }
    },
    "/wms/bins": {
      "get": {
        "operationId": "get-wms-bins",
        "tags": [
          "WMS"
        ],
        "summary": "Listar endereços",
        "description": "Os endereços de estoque (rua, prédio, nível, apartamento) de cada depósito. O `code` é o que as movimentações usam em `bin`.\n\nTodo depósito tem o endereço `ENDERECAR` (zona \"A endereçar\", `usage: staging`): é para onde vai a entrada enviada sem endereço, à espera de ser guardada pela operação no BIX.\n\nEscopo exigido: `wms.structure.read` (WMS · Estrutura (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "storage_location",
            "in": "query",
            "required": false,
            "description": "Código do depósito no WMS.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "01"
          },
          {
            "name": "updated_since",
            "in": "query",
            "required": false,
            "description": "Só registros alterados a partir desta data/hora (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T06:00:00-03:00"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 801
                          },
                          "code": {
                            "type": "string",
                            "example": "05-003-02"
                          },
                          "store": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 12
                              },
                              "code": {
                                "type": "string",
                                "example": "0012"
                              },
                              "name": {
                                "type": "string",
                                "example": "Loja Centro"
                              }
                            }
                          },
                          "storage_location": {
                            "type": "string",
                            "example": "01"
                          },
                          "zone": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "PR"
                              },
                              "name": {
                                "type": "string",
                                "example": "Prateleira"
                              },
                              "usage": {
                                "type": "string",
                                "example": "sales_floor"
                              }
                            }
                          },
                          "aisle": {
                            "type": "string",
                            "example": "05"
                          },
                          "bay": {
                            "type": "string",
                            "example": "003"
                          },
                          "level": {
                            "type": "string",
                            "example": "02"
                          },
                          "position": {
                            "type": "string",
                            "example": ""
                          },
                          "blocked_putaway": {
                            "type": "boolean",
                            "example": false
                          },
                          "blocked_removal": {
                            "type": "boolean",
                            "example": false
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          },
                          "updated_at": {
                            "type": "string",
                            "example": "2026-11-10T08:30:00-03:00"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 801,
                      "code": "05-003-02",
                      "store": {
                        "id": 12,
                        "code": "0012",
                        "name": "Loja Centro"
                      },
                      "storage_location": "01",
                      "zone": {
                        "code": "PR",
                        "name": "Prateleira",
                        "usage": "sales_floor"
                      },
                      "aisle": "05",
                      "bay": "003",
                      "level": "02",
                      "position": "",
                      "blocked_putaway": false,
                      "blocked_removal": false,
                      "active": true,
                      "updated_at": "2026-11-10T08:30:00-03:00"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.structure.read"
      }
    },
    "/wms/reasons": {
      "get": {
        "operationId": "get-wms-reasons",
        "tags": [
          "WMS"
        ],
        "summary": "Listar motivos de movimentação",
        "description": "Os motivos cadastrados no WMS do cliente. Toda entrada e saída enviada pela API leva o `code` de um motivo que valha para o tipo (`types` vazio vale para todos). A venda usa o motivo do sistema `VENDA` sozinha.\n\nEscopo exigido: `wms.structure.read` (WMS · Estrutura (leitura)).",
        "parameters": [
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "description": "Inclui os registros desativados (`active: false`). Use na sincronização incremental para saber o que saiu.",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string",
                            "example": "COMPRA"
                          },
                          "name": {
                            "type": "string",
                            "example": "Compra"
                          },
                          "types": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "example": "receipt"
                            }
                          },
                          "requires_note": {
                            "type": "boolean",
                            "example": false
                          },
                          "system": {
                            "type": "boolean",
                            "example": false
                          },
                          "active": {
                            "type": "boolean",
                            "example": true
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "code": "COMPRA",
                      "name": "Compra",
                      "types": [
                        "receipt"
                      ],
                      "requires_note": false,
                      "system": false,
                      "active": true
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.structure.read"
      }
    },
    "/wms/movements": {
      "get": {
        "operationId": "get-wms-movements",
        "tags": [
          "WMS"
        ],
        "summary": "Ler o livro de movimentações",
        "description": "Todas as movimentações de estoque do WMS, na ordem em que foram lançadas: entradas, saídas, vendas, transferências, reposições, ajustes, **ajustes de inventário** e estornos. É por aqui que o ERP replica o que a operação fez no BIX (o acerto de um inventário, por exemplo).\n\nO livro não se altera: correção é um estorno, que aparece como outro lançamento com `reversal_of`. Para sincronizar, guarde o maior `id` lido e peça `since_id` na próxima vez.\n\nEscopo exigido: `wms.movements.read` (WMS · Movimentações (leitura)).",
        "parameters": [
          {
            "name": "store_code",
            "in": "query",
            "required": false,
            "description": "Código de integração da loja.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "0012"
          },
          {
            "name": "since_id",
            "in": "query",
            "required": false,
            "description": "Só lançamentos com `id` maior que este (cursor da sincronização).",
            "schema": {
              "type": "integer"
            },
            "example": 0
          },
          {
            "name": "occurred_since",
            "in": "query",
            "required": false,
            "description": "Só lançamentos com data do movimento a partir desta.",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "example": "2026-11-10T00:00:00-03:00"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Tipo: `receipt`, `issue`, `transfer`, `replenishment`, `sale`, `adjustment`, `count_adjustment` ou `initial_load`.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "count_adjustment"
          },
          {
            "name": "product_code",
            "in": "query",
            "required": false,
            "description": "Código interno do produto.",
            "schema": {
              "type": "string",
              "description": "Lista separada por vírgula."
            },
            "example": "1001"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Página, começando em 1.",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            },
            "example": 1
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "description": "Itens por página. Acima de 100 a chamada é recusada com `invalid_parameter` (não é cortada em silêncio).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 55120
                          },
                          "occurred_at": {
                            "type": "string",
                            "example": "2026-11-10T07:40:00-03:00"
                          },
                          "recorded_at": {
                            "type": "string",
                            "example": "2026-11-10T07:41:02-03:00"
                          },
                          "type": {
                            "type": "string",
                            "example": "receipt"
                          },
                          "from": {
                            "nullable": true
                          },
                          "to": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "ENDERECAR"
                              },
                              "storage_location": {
                                "type": "string",
                                "example": "01"
                              },
                              "store": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "integer",
                                    "example": 12
                                  },
                                  "code": {
                                    "type": "string",
                                    "example": "0012"
                                  },
                                  "name": {
                                    "type": "string",
                                    "example": "Loja Centro"
                                  }
                                }
                              }
                            }
                          },
                          "product": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "example": 345
                              },
                              "internal_code": {
                                "type": "string",
                                "example": "1001"
                              },
                              "ean": {
                                "type": "string",
                                "example": "7891234567890"
                              },
                              "description": {
                                "type": "string",
                                "example": "ARROZ TIPO 1 5KG"
                              },
                              "unit": {
                                "type": "string",
                                "example": "UN"
                              }
                            }
                          },
                          "quantity": {
                            "type": "number",
                            "example": 48.0
                          },
                          "batch": {
                            "type": "string",
                            "example": ""
                          },
                          "expiry_date": {
                            "nullable": true
                          },
                          "stock_status": {
                            "type": "string",
                            "example": "available"
                          },
                          "reason": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string",
                                "example": "COMPRA"
                              },
                              "name": {
                                "type": "string",
                                "example": "Compra"
                              }
                            }
                          },
                          "document": {
                            "type": "string",
                            "example": "NF 123456"
                          },
                          "note": {
                            "type": "string",
                            "example": ""
                          },
                          "source": {
                            "type": "string",
                            "example": "integration"
                          },
                          "external_id": {
                            "type": "string",
                            "example": "NF-123456-1"
                          },
                          "reversal_of": {
                            "nullable": true
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "example": 1
                        },
                        "page_size": {
                          "type": "integer",
                          "example": 50
                        },
                        "total_items": {
                          "type": "integer",
                          "example": 1
                        },
                        "total_pages": {
                          "type": "integer",
                          "example": 1
                        },
                        "has_next": {
                          "type": "boolean",
                          "example": false
                        }
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": 55120,
                      "occurred_at": "2026-11-10T07:40:00-03:00",
                      "recorded_at": "2026-11-10T07:41:02-03:00",
                      "type": "receipt",
                      "from": null,
                      "to": {
                        "code": "ENDERECAR",
                        "storage_location": "01",
                        "store": {
                          "id": 12,
                          "code": "0012",
                          "name": "Loja Centro"
                        }
                      },
                      "product": {
                        "id": 345,
                        "internal_code": "1001",
                        "ean": "7891234567890",
                        "description": "ARROZ TIPO 1 5KG",
                        "unit": "UN"
                      },
                      "quantity": 48.0,
                      "batch": "",
                      "expiry_date": null,
                      "stock_status": "available",
                      "reason": {
                        "code": "COMPRA",
                        "name": "Compra"
                      },
                      "document": "NF 123456",
                      "note": "",
                      "source": "integration",
                      "external_id": "NF-123456-1",
                      "reversal_of": null
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "page_size": 50,
                    "total_items": 1,
                    "total_pages": 1,
                    "has_next": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "x-bix-scope": "wms.movements.read"
      },
      "post": {
        "operationId": "post-wms-movements",
        "tags": [
          "WMS"
        ],
        "summary": "Enviar entradas, saídas e vendas",
        "description": "Lança no WMS o que aconteceu no ERP: **entrada** (`receipt`: nota de compra, transferência recebida, devolução), **saída** (`issue`: transferência enviada, consumo, perda) e **venda** (`sale`). Transferência entre endereços, reposição e ajuste continuam sendo feitos pela operação no BIX.\n\nSem `bin`, o lançamento usa o endereço \"A endereçar\" do depósito: a entrada fica lá até ser guardada na prateleira pela operação, e a saída baixa de lá.\n\nO `external_id` identifica a linha no ERP e torna o envio seguro de repetir: a mesma linha enviada de novo volta `skipped`, sem lançar duas vezes; com conteúdo diferente, é recusada.\n\nEnvie até 500 itens em `{\"items\": [...]}`. Use o cabeçalho `Idempotency-Key` para poder repetir a chamada (timeout, queda de rede) sem gravar duas vezes.\n\nEscopo exigido: `wms.movements.write` (WMS · Movimentações (envio)).",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Chave única da operação (até 100 caracteres). Repetir a chamada com a mesma chave devolve a resposta da primeira, sem gravar de novo, por 24 horas.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "example": 2
                        },
                        "created": {
                          "type": "integer",
                          "example": 2
                        },
                        "updated": {
                          "type": "integer",
                          "example": 0
                        },
                        "skipped": {
                          "type": "integer",
                          "example": 0
                        },
                        "errors": {
                          "type": "integer",
                          "example": 0
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": {
                            "type": "integer",
                            "example": 0
                          },
                          "status": {
                            "type": "string",
                            "example": "created"
                          },
                          "id": {
                            "type": "integer",
                            "example": 55120
                          },
                          "code": {
                            "nullable": true
                          },
                          "detail": {
                            "nullable": true
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "summary": {
                    "total": 2,
                    "created": 2,
                    "updated": 0,
                    "skipped": 0,
                    "errors": 0
                  },
                  "results": [
                    {
                      "index": 0,
                      "status": "created",
                      "id": 55120,
                      "code": null,
                      "detail": null
                    },
                    {
                      "index": 1,
                      "status": "created",
                      "id": 55121,
                      "code": null,
                      "detail": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter`: Parâmetro com valor inválido (o `detail` diz qual).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "invalid_parameter",
                  "detail": "Parâmetro com valor inválido (o `detail` diz qual)."
                }
              }
            }
          },
          "401": {
            "description": "`api_key_expired`: A chave passou da data de expiração. · `api_key_revoked`: A chave foi revogada na Configuração Global › API. · `invalid_api_key`: A chave não existe neste ambiente ou está errada. · `missing_api_key`: A chamada veio sem o cabeçalho \"Authorization: Bearer <chave>\".",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "api_key_expired",
                  "detail": "A chave passou da data de expiração."
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: A chave não tem o acesso que este endpoint exige. · `module_disabled`: O cliente não tem o módulo deste endpoint habilitado. · `store_not_allowed`: A chave está restrita a algumas lojas e uma das pedidas não é delas.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "insufficient_scope",
                  "detail": "A chave não tem o acesso que este endpoint exige."
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_reused`: O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "idempotency_key_reused",
                  "detail": "O `Idempotency-Key` já foi usado, nas últimas 24 horas, numa chamada com outro corpo."
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "rate_limited",
                  "detail": "Limite de chamadas por minuto da chave atingido. Respeite o `Retry-After`."
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`: Erro interno. Tente de novo; se persistir, fale com o suporte.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "detail"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "description": "Código estável: decida por ele."
                    },
                    "detail": {
                      "type": "string",
                      "description": "Mensagem para a pessoa. Pode mudar."
                    }
                  }
                },
                "example": {
                  "code": "internal_error",
                  "detail": "Erro interno. Tente de novo; se persistir, fale com o suporte."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "external_id",
                        "type",
                        "storage_location",
                        "quantity"
                      ],
                      "properties": {
                        "external_id": {
                          "type": "string",
                          "description": "Identificador único da linha no ERP (até 80 caracteres), por exemplo nota + item.",
                          "example": "NF-123456-1"
                        },
                        "type": {
                          "type": "string",
                          "description": "`receipt` (entrada), `issue` (saída) ou `sale` (venda).",
                          "example": "receipt"
                        },
                        "store_code": {
                          "type": "string",
                          "description": "Código de integração da loja. Ou `store_id`.",
                          "example": "0012"
                        },
                        "store_id": {
                          "type": "integer",
                          "description": "Id da loja no BIX. Ou `store_code`."
                        },
                        "storage_location": {
                          "type": "string",
                          "description": "Código do depósito no WMS (ver `GET /wms/storage-locations`).",
                          "example": "01"
                        },
                        "bin": {
                          "type": "string",
                          "description": "Código do endereço. Vazio: o \"A endereçar\" do depósito."
                        },
                        "internal_code": {
                          "type": "string",
                          "description": "Código interno: quantidade na unidade do item de estoque. Ou `ean`.",
                          "example": "1001"
                        },
                        "ean": {
                          "type": "string",
                          "description": "Código de barras: quantidade na unidade daquele código (a caixa de 12 conta 12). Ou `internal_code`."
                        },
                        "quantity": {
                          "type": "number",
                          "description": "Quantidade, maior que zero.",
                          "example": 48
                        },
                        "batch": {
                          "type": "string",
                          "description": "Lote (até 40 caracteres)."
                        },
                        "expiry_date": {
                          "type": "string",
                          "description": "Validade do lote (AAAA-MM-DD)."
                        },
                        "reason": {
                          "type": "string",
                          "description": "Código do motivo (ver `GET /wms/reasons`). Obrigatório em `receipt` e `issue`; a venda usa `VENDA`.",
                          "example": "COMPRA"
                        },
                        "document": {
                          "type": "string",
                          "description": "Documento de origem (nota, pedido), até 80 caracteres.",
                          "example": "NF 123456"
                        },
                        "note": {
                          "type": "string",
                          "description": "Observação (até 255 caracteres)."
                        },
                        "occurred_at": {
                          "type": "string",
                          "description": "Data e hora do movimento no ERP (ISO 8601). Vazio: agora.",
                          "example": "2026-11-10T07:40:00-03:00"
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "items": [
                  {
                    "external_id": "NF-123456-1",
                    "type": "receipt",
                    "store_code": "0012",
                    "storage_location": "01",
                    "internal_code": "1001",
                    "quantity": 48,
                    "reason": "COMPRA",
                    "document": "NF 123456",
                    "occurred_at": "2026-11-10T07:40:00-03:00"
                  },
                  {
                    "external_id": "CUPOM-998877-3",
                    "type": "sale",
                    "store_code": "0012",
                    "storage_location": "01",
                    "bin": "ENDERECAR",
                    "internal_code": "1001",
                    "quantity": 2,
                    "occurred_at": "2026-11-10T09:15:00-03:00"
                  }
                ]
              }
            }
          }
        },
        "x-bix-scope": "wms.movements.write"
      }
    }
  }
}