{
  "openapi": "3.1.0",
  "info": {
    "title": "API do Softeum Pedidos",
    "version": "1.0.0",
    "description": "Integração do ERP da indústria com o Softeum Pedidos.\n\n**Pedidos (Softeum → ERP).** Quando um pedido fica pronto, o Softeum avisa o endereço cadastrado no painel (webhook `pedido.aprovado`).\nO ERP responde 2xx e confirma com o número do ERP: no próprio corpo da resposta ou depois, em `POST /pedidos/{id}/confirmacao`.\nSe não conseguir lançar, recusa com o motivo em `POST /pedidos/{id}/recusa`, e o pedido volta para o time da indústria.\nSem webhook, o ERP busca em `GET /pedidos?situacao=pronto` (o pedido fica pronto até ser confirmado ou recusado).\n\n**Cadastros (ERP → Softeum).** O ERP é a fonte da verdade de produtos, compradores, vendedores e tabelas de preço.\nEnvie em lotes de até 1000 registros. Cada um é criado ou atualizado pelo `codigo_erp`; para desativar, mande `ativo: false`.\n\n**Autenticação.** `Authorization: Bearer <chave>`, com a chave criada no painel (Integração → Como o ERP recebe → O ERP busca os pedidos)."
  },
  "servers": [
    {
      "url": "https://api.softeum.com.br/v1",
      "description": "Versão 1 da API."
    }
  ],
  "security": [
    {
      "chave": []
    }
  ],
  "tags": [
    {
      "name": "Pedidos",
      "description": "Buscar, confirmar e recusar pedidos."
    },
    {
      "name": "Cadastros",
      "description": "Sincronizar os cadastros do ERP."
    }
  ],
  "paths": {
    "/pedidos": {
      "get": {
        "summary": "Listar pedidos",
        "description": "Do mais antigo para o mais novo. Use para buscar os pedidos prontos quando não houver webhook.",
        "tags": [
          "Pedidos"
        ],
        "parameters": [
          {
            "name": "situacao",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pronto",
                "enviado",
                "confirmado",
                "erro"
              ]
            }
          },
          {
            "name": "desde",
            "in": "query",
            "description": "Aprovados a partir deste momento (ISO 8601 com fuso).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "proximo_cursor da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Uma página de pedidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaPedidos"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos: erros[] traz cada campo e o motivo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/pedidos/{id}": {
      "get": {
        "summary": "Buscar um pedido",
        "tags": [
          "Pedidos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "id do pedido no Softeum.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "O pedido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pedido"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "404": {
            "description": "Pedido não encontrado, ou ainda não pronto para o ERP (na leitura ou na revisão), recusado ou cancelado pelo time.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "O pedido não pode ir ao ERP (item sem produto do catálogo, produto inativo ou comprador sem cadastro): voltou para a revisão do time e não aparece na lista até ser aprovado de novo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/pedidos/{id}/confirmacao": {
      "post": {
        "summary": "Confirmar que o ERP lançou o pedido",
        "description": "Informe o número do pedido no ERP. Repetir com o mesmo número não muda nada.",
        "tags": [
          "Pedidos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "id do pedido no Softeum.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "Prefer",
            "in": "header",
            "required": false,
            "description": "Opcional. `return=minimal` (RFC 7240): a resposta traz só o resumo do pedido (id, situacao, numero_erp), mais rápida, e o cabeçalho Preference-Applied. Sem ele, o pedido inteiro.",
            "schema": {
              "type": "string",
              "example": "return=minimal"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmacaoErp"
              },
              "example": {
                "numero_erp": "584460"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pedido confirmado. O pedido inteiro; com `Prefer: return=minimal`, só o resumo.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Pedido"
                    },
                    {
                      "$ref": "#/components/schemas/ResumoPedido"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "404": {
            "description": "Pedido não encontrado.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "O pedido já foi confirmado com outro número, ou não está pronto para o ERP.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos: erros[] traz cada campo e o motivo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/pedidos/{id}/recusa": {
      "post": {
        "summary": "Recusar o pedido no ERP",
        "description": "O pedido fica com erro e o motivo aparece para o time da indústria, que corrige e reenvia.",
        "tags": [
          "Pedidos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "id do pedido no Softeum.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "Prefer",
            "in": "header",
            "required": false,
            "description": "Opcional. `return=minimal` (RFC 7240): a resposta traz só o resumo do pedido (id, situacao, numero_erp), mais rápida, e o cabeçalho Preference-Applied. Sem ele, o pedido inteiro.",
            "schema": {
              "type": "string",
              "example": "return=minimal"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecusaErp"
              },
              "example": {
                "motivo": "Condição de pagamento 28/56 não existe no ERP."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pedido marcado com erro. O pedido inteiro; com `Prefer: return=minimal`, só o resumo.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Pedido"
                    },
                    {
                      "$ref": "#/components/schemas/ResumoPedido"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "404": {
            "description": "Pedido não encontrado.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "409": {
            "description": "O pedido já foi confirmado, ou não está pronto para o ERP.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos: erros[] traz cada campo e o motivo.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/pedidos/{id}/arquivo": {
      "get": {
        "summary": "Baixar o documento original",
        "tags": [
          "Pedidos"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "id do pedido no Softeum.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redireciona para um link temporário do arquivo (PDF, planilha, XML ou e-mail)."
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "404": {
            "description": "Pedido não encontrado.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/produtos": {
      "put": {
        "summary": "Sincronizar produtos",
        "description": "Cria ou atualiza produtos do catálogo pelo codigo_erp.",
        "tags": [
          "Cadastros"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoteProdutos"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lote processado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoSincronizacao"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "O lote todo é inválido (sem a lista, vazio ou com mais registros que o máximo). Registro inválido sozinho não derruba o lote: volta em erros.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/compradores": {
      "put": {
        "summary": "Sincronizar compradores",
        "description": "Cria ou atualiza compradores pelo codigo_erp.",
        "tags": [
          "Cadastros"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoteCompradores"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lote processado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoSincronizacao"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "O lote todo é inválido (sem a lista, vazio ou com mais registros que o máximo). Registro inválido sozinho não derruba o lote: volta em erros.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/vendedores": {
      "put": {
        "summary": "Sincronizar vendedores",
        "description": "Cria ou atualiza vendedores pelo codigo_erp.",
        "tags": [
          "Cadastros"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoteVendedores"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lote processado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoSincronizacao"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "O lote todo é inválido (sem a lista, vazio ou com mais registros que o máximo). Registro inválido sozinho não derruba o lote: volta em erros.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    },
    "/tabelas-de-preco/{codigo_erp}": {
      "put": {
        "summary": "Enviar uma tabela de preço inteira",
        "description": "Cria ou substitui a tabela e todos os preços dela. Preço que não vier sai da tabela.",
        "tags": [
          "Cadastros"
        ],
        "parameters": [
          {
            "name": "codigo_erp",
            "in": "path",
            "required": true,
            "description": "Código da tabela no ERP.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. As operações já são idempotentes: repetir a mesma chamada (com ou sem esta chave) não muda nada duas vezes.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TabelaPrecoErp"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tabela gravada (contagem dos preços).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultadoSincronizacao"
                }
              }
            }
          },
          "401": {
            "description": "Chave de acesso ausente, inválida ou revogada.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "403": {
            "description": "O acesso da empresa ao Softeum está suspenso.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "422": {
            "description": "Tabela inválida (ex.: vigência que se sobrepõe a outra do mesmo alcance).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          },
          "429": {
            "description": "Muitas chamadas em pouco tempo (padrão: 120 por minuto por chave; a empresa pode ter um limite maior, combinado com a Softeum). Espere o tempo do cabeçalho Retry-After.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problema"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "pedido.aprovado": {
      "post": {
        "summary": "Pedido pronto para o ERP",
        "description": "Enviado ao endereço cadastrado no painel (Integração → Como o ERP recebe → Aviso no endereço do ERP).\nCabeçalhos: `Softeum-Evento` (tipo), `Softeum-Entrega` (id do aviso) e `Softeum-Assinatura: t=<segundos>,v1=<hex>`.\nv1 = HMAC-SHA256(segredo, `<t>.<corpo>`), com o segredo mostrado no painel.\nRecuse avisos com mais de 5 minutos e use o pedido.id para não lançar duas vezes.\nSem resposta 2xx em 10 segundos, reenviamos depois de 1, 5, 30, 120, 360 minutos; depois disso o pedido fica com erro.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventoPedido"
              },
              "example": {
                "id": "0199a3c4-5f10-7a2b-8c3d-4e5f60718294",
                "tipo": "pedido.aprovado",
                "criado_em": "2026-09-30T16:42:05-03:00",
                "pedido": {
                  "id": "0199a3c4-5f10-7a2b-8c3d-4e5f60718293",
                  "numero_comprador": "45882",
                  "situacao": "pronto",
                  "origem": "pdf",
                  "recebido_em": "2026-09-30T16:13:00-03:00",
                  "aprovado_em": "2026-09-30T16:42:00-03:00",
                  "comprador": {
                    "cnpj": "12345678000195",
                    "razao_social": "Distribuidora Rio Claro Ltda",
                    "codigo_erp": "C001"
                  },
                  "vendedor": {
                    "nome": "Carlos Menezes",
                    "email": "carlos.menezes@valeazul.com.br",
                    "codigo_erp": null
                  },
                  "condicao_pagamento": "28/42/56 dias",
                  "data_pedido": "2026-09-29",
                  "data_entrega": "2026-10-07",
                  "endereco_entrega": "CD Rio Claro, Av. Brasil, 2150",
                  "observacoes": null,
                  "itens": [
                    {
                      "linha": 4,
                      "codigo_comprador": "004359",
                      "descricao_comprador": "LIMPA VIDROS REFIL 500ML CX12",
                      "produto": {
                        "sku": "VA-LVD-500R",
                        "codigo_erp": "4359",
                        "descricao": "Limpa-vidros refil 500 ml",
                        "ean": "7896543000415"
                      },
                      "quantidade": 30,
                      "unidade": "CX",
                      "quantidade_erp": 360,
                      "unidade_erp": "UN",
                      "preco_unitario": 76.04,
                      "valor_total": 2281.2,
                      "data_entrega": null
                    }
                  ],
                  "valor_total": 2281.2,
                  "revisao": {
                    "revisado_por": "Marina Costa",
                    "revisado_em": "2026-09-30T16:40:00-03:00",
                    "motivos": [
                      "preco"
                    ]
                  },
                  "numero_erp": null,
                  "arquivo_original": "https://arquivos.exemplo.com/pedido-45882.pdf"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Se já lançou, devolva o número do ERP para confirmar na hora.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RespostaAviso"
                }
              }
            }
          }
        }
      }
    },
    "teste": {
      "post": {
        "summary": "Aviso de teste",
        "description": "Enviado só quando alguém usa o botão Enviar teste no painel (Integração → Como o ERP recebe → Aviso no endereço do ERP). Não leva pedido.\nMesmos cabeçalhos do aviso de pedido, com `Softeum-Evento: teste`.\nConfira a assinatura e responda 2xx; não lance nada.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventoTeste"
              },
              "example": {
                "id": "0199a3c4-5f10-7a2b-8c3d-4e5f60718295",
                "tipo": "teste",
                "criado_em": "2026-09-30T16:45:00-03:00"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problema": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Endereço que identifica o tipo de erro.",
            "examples": [
              "https://softeum.com.br/erros/validacao"
            ]
          },
          "title": {
            "type": "string",
            "examples": [
              "Dados inválidos"
            ]
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string"
          },
          "erros": {
            "description": "Um item por campo com problema: até 100 (o detail diz quantos são ao todo).",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "campo": {
                  "type": "string",
                  "examples": [
                    "produtos[3].ean"
                  ]
                },
                "mensagem": {
                  "type": "string",
                  "examples": [
                    "EAN com dígito verificador inválido."
                  ]
                }
              },
              "required": [
                "campo",
                "mensagem"
              ]
            }
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      },
      "DescontoDoItem": {
        "type": "object",
        "properties": {
          "percentual": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "description": "O percentual escrito no documento (10,50% → 10.5): maior que 0 e até 100 (100: o item bonificado). Até 4 casas.",
            "examples": [
              10.5
            ]
          },
          "tipo": {
            "type": "string",
            "enum": [
              "comercial",
              "especial",
              "promocional"
            ],
            "description": "O tipo escrito junto do desconto.",
            "examples": [
              "comercial"
            ]
          }
        },
        "required": [
          "percentual",
          "tipo"
        ]
      },
      "ItemPedido": {
        "type": "object",
        "properties": {
          "linha": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991,
            "description": "Posição do item no documento do comprador."
          },
          "codigo_comprador": {
            "description": "Código do produto como o comprador escreveu.",
            "examples": [
              "004359"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "descricao_comprador": {
            "examples": [
              "LIMPA VIDROS REFIL 500ML CX12"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "produto": {
            "type": "object",
            "properties": {
              "sku": {
                "type": "string",
                "examples": [
                  "VA-LVD-500R"
                ]
              },
              "codigo_erp": {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "Código do registro no ERP do cliente.",
                    "examples": [
                      "C001"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "descricao": {
                "type": "string",
                "examples": [
                  "Limpa-vidros refil 500 ml"
                ]
              },
              "ean": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "sku",
              "codigo_erp",
              "descricao",
              "ean"
            ]
          },
          "quantidade": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Quantidade como o comprador pediu.",
            "examples": [
              30
            ]
          },
          "unidade": {
            "examples": [
              "CX"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "quantidade_erp": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Quantidade já convertida para a unidade do ERP (ex.: 30 CX → 360 UN).",
            "examples": [
              360
            ]
          },
          "unidade_erp": {
            "type": "string",
            "description": "Unidade de quantidade_erp, do cadastro do produto (nunca do texto do comprador): a embalagem do produto vendido por medida (KG, L, M) ou com 1 unidade (CX); UN na embalagem com mais de uma.",
            "examples": [
              "UN"
            ]
          },
          "preco_unitario": {
            "type": "number",
            "minimum": 0,
            "description": "Preço que vai para o ERP, por unidade do comprador: o do pedido, o decidido na revisão ou o da tabela de preço, conforme a regra de preço da indústria. Já vem com o desconto do pedido: o desconto do próprio item e o desconto sobre o total, distribuído nos itens em proporção ao valor de cada um (a soma dos itens dá o total do documento).",
            "examples": [
              76.04
            ]
          },
          "valor_total": {
            "type": "number",
            "minimum": 0,
            "description": "Reais, até 2 casas decimais.",
            "examples": [
              2281.2
            ]
          },
          "data_entrega": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                "examples": [
                  "2026-10-07"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Data de entrega deste item, quando o documento do comprador traz uma por item. Nula: vale a data_entrega do pedido."
          },
          "desconto": {
            "description": "O desconto do próprio item, como está no documento. Só vem quando a indústria lê o desconto de cada item (a equipe Softeum liga); nela, null no item sem desconto. O preco_unitario já vem com esse desconto: não aplique de novo (o preço de tabela do pedido é preco_unitario ÷ (1 − percentual ÷ 100)).",
            "anyOf": [
              {
                "$ref": "#/components/schemas/DescontoDoItem"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "linha",
          "codigo_comprador",
          "descricao_comprador",
          "produto",
          "quantidade",
          "unidade",
          "quantidade_erp",
          "unidade_erp",
          "preco_unitario",
          "valor_total",
          "data_entrega"
        ]
      },
      "Pedido": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "Identificador do pedido no Softeum. Use como chave para não lançar o mesmo pedido duas vezes."
          },
          "teste": {
            "description": "Só no pedido de teste, criado no painel (Integração → Como o ERP recebe → O ERP busca os pedidos → Criar pedido de teste) para a TI testar a busca, a confirmação e a recusa. Ele vem com os cadastros da indústria, então o ERP de homologação consegue lançá-lo; no ERP de produção, recuse com o motivo (o pedido sai da fila). Nos outros pedidos a chave nem aparece.",
            "type": "boolean",
            "const": true
          },
          "numero_comprador": {
            "type": "string",
            "description": "Número do pedido no documento do comprador.",
            "examples": [
              "45882"
            ]
          },
          "situacao": {
            "type": "string",
            "enum": [
              "pronto",
              "enviado",
              "confirmado",
              "erro"
            ],
            "description": "pronto: aprovado e esperando o ERP; enviado: o aviso chegou ao ERP; confirmado: o ERP lançou e devolveu o número; erro: o ERP recusou ou não respondeu."
          },
          "origem": {
            "type": "string",
            "enum": [
              "pdf",
              "word",
              "excel",
              "xml",
              "imagem",
              "corpo",
              "importado"
            ],
            "description": "De onde o pedido foi lido: anexo PDF, documento Word (.docx), planilha, XML, imagem (foto ou print do pedido, anexado ou colado no e-mail), texto do e-mail ou arquivo importado no painel. Trate um valor desconhecido como genérico: a lista pode crescer."
          },
          "recebido_em": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "examples": [
              "2026-09-30T16:13:00-03:00"
            ],
            "description": "Quando o e-mail chegou."
          },
          "aprovado_em": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "examples": [
              "2026-09-30T16:13:00-03:00"
            ],
            "description": "Quando o pedido ficou pronto (direto ou depois da revisão)."
          },
          "comprador": {
            "type": "object",
            "properties": {
              "cnpj": {
                "type": "string",
                "pattern": "^\\d{14}$",
                "description": "CNPJ só com números (14 dígitos), com dígitos verificadores válidos: o do comprador do cadastro do Softeum (o lido do documento fica no histórico do pedido).",
                "examples": [
                  "12345678000195"
                ]
              },
              "razao_social": {
                "type": "string",
                "examples": [
                  "Distribuidora Rio Claro Ltda"
                ]
              },
              "codigo_erp": {
                "anyOf": [
                  {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "Código do registro no ERP do cliente.",
                    "examples": [
                      "C001"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "cnpj",
              "razao_social",
              "codigo_erp"
            ]
          },
          "vendedor": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "examples": [
                      "Carlos Menezes"
                    ]
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                    "examples": [
                      "carlos.menezes@valeazul.com.br"
                    ]
                  },
                  "codigo_erp": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 60,
                        "description": "Código do registro no ERP do cliente.",
                        "examples": [
                          "C001"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "nome",
                  "email",
                  "codigo_erp"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Vendedor que encaminhou o e-mail."
          },
          "condicao_pagamento": {
            "examples": [
              "28/42/56 dias"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "data_pedido": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                "examples": [
                  "2026-10-07"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Data em que o comprador fez o pedido, como o documento traz (a emissão). Nula quando o documento não traz: use recebido_em. O e-mail encaminhado dias depois não muda esta data."
          },
          "data_entrega": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                "examples": [
                  "2026-10-07"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Data de entrega do pedido. Quando os itens trazem datas diferentes, o pedido passou pela revisão, e a de cada item vem em itens[].data_entrega."
          },
          "endereco_entrega": {
            "type": [
              "string",
              "null"
            ]
          },
          "observacoes": {
            "type": [
              "string",
              "null"
            ]
          },
          "itens": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemPedido"
            }
          },
          "valor_total": {
            "type": "number",
            "minimum": 0,
            "description": "Soma do valor_total dos itens, já com as decisões da revisão (item tirado do pedido não entra).",
            "examples": [
              2281.2
            ]
          },
          "revisao": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "revisado_por": {
                    "type": "string",
                    "examples": [
                      "Marina Costa"
                    ]
                  },
                  "revisado_em": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "examples": [
                      "2026-09-30T16:13:00-03:00"
                    ]
                  },
                  "motivos": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Os códigos do que mandou o pedido para a revisão: `preco`, `depara`, `cnpj`, `faltam`, `catalogo`, `duplicado`, `valor`, `leitura` e `sempre_revisar`. Os avisos, que não mandam o pedido para a revisão, não entram.",
                    "examples": [
                      [
                        "preco"
                      ]
                    ]
                  }
                },
                "required": [
                  "revisado_por",
                  "revisado_em",
                  "motivos"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Preenchido quando o pedido passou pela revisão do time."
          },
          "numero_erp": {
            "description": "Número do pedido no ERP, depois da confirmação.",
            "examples": [
              "584460"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "arquivo_original": {
            "type": "string",
            "format": "uri",
            "description": "Link temporário para baixar o documento original do comprador."
          }
        },
        "required": [
          "id",
          "numero_comprador",
          "situacao",
          "origem",
          "recebido_em",
          "aprovado_em",
          "comprador",
          "vendedor",
          "condicao_pagamento",
          "data_pedido",
          "data_entrega",
          "endereco_entrega",
          "observacoes",
          "itens",
          "valor_total",
          "revisao",
          "numero_erp",
          "arquivo_original"
        ]
      },
      "ConfirmacaoErp": {
        "type": "object",
        "properties": {
          "numero_erp": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Número do pedido no ERP.",
            "examples": [
              "584460"
            ]
          },
          "lancado_em": {
            "description": "Quando o ERP lançou o pedido (se não vier, vale a hora da confirmação).",
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "examples": [
              "2026-09-30T16:13:00-03:00"
            ]
          }
        },
        "required": [
          "numero_erp"
        ]
      },
      "RecusaErp": {
        "type": "object",
        "properties": {
          "motivo": {
            "type": "string",
            "minLength": 3,
            "maxLength": 500,
            "description": "Por que o ERP não aceitou. Aparece para o time da indústria no painel.",
            "examples": [
              "Condição de pagamento 28/56 não existe no ERP."
            ]
          }
        },
        "required": [
          "motivo"
        ]
      },
      "ResumoPedido": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "id do pedido no Softeum."
          },
          "situacao": {
            "type": "string",
            "enum": [
              "pronto",
              "enviado",
              "confirmado",
              "erro"
            ],
            "description": "A situação depois da confirmação (confirmado) ou da recusa (erro)."
          },
          "numero_erp": {
            "description": "Número do pedido no ERP (null enquanto não confirmado).",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "situacao",
          "numero_erp"
        ],
        "additionalProperties": false
      },
      "ListaPedidos": {
        "type": "object",
        "properties": {
          "dados": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pedido"
            }
          },
          "proximo_cursor": {
            "description": "Passe em ?cursor= para buscar a próxima página. null = acabou.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "dados",
          "proximo_cursor"
        ]
      },
      "ProdutoErp": {
        "type": "object",
        "properties": {
          "codigo_erp": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Código do registro no ERP do cliente.",
            "examples": [
              "C001"
            ]
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "examples": [
              "VA-LVD-500R"
            ]
          },
          "descricao": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "examples": [
              "Limpa-vidros refil 500 ml"
            ]
          },
          "ean": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(\\d{8}|\\d{12,14})$"
              },
              {
                "type": "null"
              }
            ]
          },
          "embalagem": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "description": "Embalagem de venda.",
            "examples": [
              "CX"
            ]
          },
          "unidades_por_embalagem": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 9007199254740991,
            "examples": [
              12
            ]
          },
          "ncm": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^\\d{8}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "ipi_pct": {
            "default": 0,
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "linha": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ]
          },
          "ativo": {
            "default": true,
            "type": "boolean"
          }
        },
        "required": [
          "codigo_erp",
          "sku",
          "descricao",
          "embalagem",
          "unidades_por_embalagem"
        ]
      },
      "CompradorErp": {
        "type": "object",
        "properties": {
          "codigo_erp": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Código do registro no ERP do cliente.",
            "examples": [
              "C001"
            ]
          },
          "cnpj": {
            "type": "string",
            "pattern": "^\\d{14}$",
            "description": "CNPJ só com números (14 dígitos), com dígitos verificadores válidos.",
            "examples": [
              "12345678000195"
            ]
          },
          "razao_social": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "nome_fantasia": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "cidade": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 120
              },
              {
                "type": "null"
              }
            ]
          },
          "uf": {
            "description": "Estado do comprador, a sigla com 2 letras maiúsculas. Casa com a tabela de preço pelos estados, criada no painel.",
            "examples": [
              "SP"
            ],
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[A-Z]{2}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "regiao": {
            "description": "Região de preço (casa com as tabelas de nível região).",
            "examples": [
              "Sudeste"
            ],
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60
              },
              {
                "type": "null"
              }
            ]
          },
          "codigo_vendedor": {
            "description": "codigo_erp do vendedor responsável.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Código do registro no ERP do cliente.",
                "examples": [
                  "C001"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "codigo_tabela_preco": {
            "description": "codigo_erp da tabela do comprador (nível 2), se houver.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Código do registro no ERP do cliente.",
                "examples": [
                  "C001"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "ativo": {
            "default": true,
            "description": "false = bloqueado: pedidos dele vão para a revisão.",
            "type": "boolean"
          }
        },
        "required": [
          "codigo_erp",
          "cnpj",
          "razao_social"
        ]
      },
      "VendedorErp": {
        "type": "object",
        "properties": {
          "codigo_erp": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60,
            "description": "Código do registro no ERP do cliente.",
            "examples": [
              "C001"
            ]
          },
          "nome": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "email": {
            "description": "E-mail que encaminha os pedidos. Outros endereços do mesmo vendedor se cadastram no painel.",
            "anyOf": [
              {
                "type": "string",
                "format": "email",
                "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
                "examples": [
                  "carlos.menezes@valeazul.com.br"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "ativo": {
            "default": true,
            "type": "boolean"
          }
        },
        "required": [
          "codigo_erp",
          "nome"
        ]
      },
      "TabelaPrecoErp": {
        "type": "object",
        "properties": {
          "nome": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "examples": [
              "Tabela Sudeste"
            ]
          },
          "nivel": {
            "type": "string",
            "enum": [
              "especifico",
              "comprador",
              "regiao",
              "padrao"
            ],
            "description": "Em cada item vale o primeiro que tiver preço: especifico (de um comprador), comprador (tabela atribuída ao comprador), regiao, padrao."
          },
          "codigo_comprador": {
            "description": "Obrigatório no nível especifico.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 60,
                "description": "Código do registro no ERP do cliente.",
                "examples": [
                  "C001"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "regiao": {
            "description": "Obrigatória no nível regiao.",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 60
              },
              {
                "type": "null"
              }
            ]
          },
          "vigencia_inicio": {
            "type": "string",
            "format": "date",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
            "examples": [
              "2026-10-07"
            ]
          },
          "vigencia_fim": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                "examples": [
                  "2026-10-07"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "precos": {
            "maxItems": 20000,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "codigo_produto": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 60,
                  "description": "codigo_erp do produto.",
                  "examples": [
                    "C001"
                  ]
                },
                "preco": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Preço líquido (sem impostos) por embalagem de venda.",
                  "examples": [
                    76.04
                  ]
                }
              },
              "required": [
                "codigo_produto",
                "preco"
              ]
            },
            "description": "Todos os preços da tabela: o que não vier aqui sai da tabela."
          }
        },
        "required": [
          "nome",
          "nivel",
          "vigencia_inicio",
          "precos"
        ]
      },
      "LoteProdutos": {
        "type": "object",
        "properties": {
          "produtos": {
            "minItems": 1,
            "maxItems": 1000,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProdutoErp"
            }
          }
        },
        "required": [
          "produtos"
        ]
      },
      "LoteCompradores": {
        "type": "object",
        "properties": {
          "compradores": {
            "minItems": 1,
            "maxItems": 1000,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompradorErp"
            }
          }
        },
        "required": [
          "compradores"
        ]
      },
      "LoteVendedores": {
        "type": "object",
        "properties": {
          "vendedores": {
            "minItems": 1,
            "maxItems": 1000,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VendedorErp"
            }
          }
        },
        "required": [
          "vendedores"
        ]
      },
      "ResultadoSincronizacao": {
        "type": "object",
        "properties": {
          "criados": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "atualizados": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "erros": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "indice": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "campo": {
                  "type": "string"
                },
                "mensagem": {
                  "type": "string"
                }
              },
              "required": [
                "indice",
                "campo",
                "mensagem"
              ]
            },
            "description": "Registros recusados (o resto do lote é gravado)."
          }
        },
        "required": [
          "criados",
          "atualizados",
          "erros"
        ]
      },
      "EventoPedido": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "Identificador deste aviso (o mesmo nos reenvios)."
          },
          "tipo": {
            "type": "string",
            "enum": [
              "pedido.aprovado"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "examples": [
              "2026-09-30T16:13:00-03:00"
            ]
          },
          "pedido": {
            "$ref": "#/components/schemas/Pedido"
          }
        },
        "required": [
          "id",
          "tipo",
          "criado_em",
          "pedido"
        ]
      },
      "EventoTeste": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "Identificador deste aviso."
          },
          "tipo": {
            "type": "string",
            "const": "teste"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "examples": [
              "2026-09-30T16:13:00-03:00"
            ]
          }
        },
        "required": [
          "id",
          "tipo",
          "criado_em"
        ]
      },
      "RespostaAviso": {
        "type": "object",
        "properties": {
          "numero_erp": {
            "description": "Se o ERP já lançou o pedido ao receber o aviso, devolva o número aqui e ele fica confirmado na hora.",
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          }
        },
        "description": "Corpo opcional da resposta 2xx do ERP."
      }
    },
    "securitySchemes": {
      "chave": {
        "type": "http",
        "scheme": "bearer",
        "description": "Chave de acesso criada no painel (Integração → Como o ERP recebe → O ERP busca os pedidos)."
      }
    }
  }
}
