{
  "openapi": "3.0.1",
  "info": {
    "title": "Atendevet API — Integração",
    "description": "Rotas que aceitam chave de API. Crie a chave nas Configurações corporativas → Configurações → Chaves de API e envie no cabeçalho `X-Api-Key`. Cada rota diz o escopo que exige; a chave vê só a clínica de quem a criou e nunca mais do que essa pessoa vê no app. Datas por dia seguem o cabeçalho `X-Timezone` (IANA, ex.: America/Sao_Paulo; sem ele, Brasília).\n\n## Webhooks\n\nAlém de consultar pela chave, o seu sistema pode ser avisado quando algo acontece na clínica. A clínica cadastra o endereço e escolhe os eventos em **Configurações corporativas → Configurações → Webhooks de saída**, e de lá pode mandar um envio de teste.\n\n### Como o aviso chega\n\nUm `POST` com JSON no endereço cadastrado, com estes cabeçalhos:\n\n| Cabeçalho | O que traz |\n| --- | --- |\n| `X-Atendevet-Event` | O evento, por exemplo `agendamento.criado`. |\n| `X-Atendevet-Delivery` | O número do envio, igual ao `id` do corpo. É o mesmo quando o envio é tentado de novo. |\n| `X-Atendevet-Signature` | `sha256=` seguido do HMAC-SHA256 do corpo em hexadecimal minúsculo, calculado com o segredo do webhook. Só vem quando o webhook tem segredo. |\n\nO corpo segue o modelo `EnvioDeWebhook`:\n\n```json\n{\n  \"id\": \"6f1c2d3e-8a4b-4c5d-9e0f-1a2b3c4d5e6f\",\n  \"evento\": \"agendamento.criado\",\n  \"criadoEm\": \"2026-11-09T14:00:00+00:00\",\n  \"teste\": false,\n  \"versao\": 1,\n  \"dados\": { }\n}\n```\n\n### Como responder\n\nResponda com qualquer status 2xx em até 10 segundos. Sem essa resposta, o envio pode ser tentado de novo: use o `id` para não processar o mesmo aviso duas vezes. O envio de teste chega com `\"teste\": true` e dados fictícios.\n\n### Como conferir a assinatura\n\nCadastre o webhook com um segredo. Calcule o HMAC-SHA256 do corpo exatamente como chegou, com esse segredo, e compare com `X-Atendevet-Signature` em tempo constante. Em Node.js:\n\n```js\nconst crypto = require(\"crypto\");\nconst esperado = \"sha256=\" + crypto.createHmac(\"sha256\", segredo).update(corpoBruto).digest(\"hex\");\nconst valido = esperado.length === assinatura.length\n  && crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(assinatura));\n```\n\n### Eventos\n\nA clínica escolhe quais eventos cada webhook recebe. Cada um diz o que trafega nele.\n\n#### Financeiro\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `orcamento.aprovado` | Orçamento aprovado (contratado) | nº da nota, responsável legal (nome/CPF/e-mail), itens com serviço/quantidade/valores, desconto, executante |\n| `pagamento.recebido` | Pagamento registrado na nota | nota, valor, forma de pagamento, data, saldo restante |\n| `cobranca.gerada` | Cobrança online gerada | nota, valor, vencimento, link do checkout |\n| `cobranca.vencida` | Cobrança online vencida | nota, valor, vencimento |\n| `repasse.calculado` | Repasse/comissão calculado | beneficiário, valor do repasse, nota de origem |\n\n#### Clientes\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `tutor.criado` | Responsável legal cadastrado | nome, e-mail, telefone, endereço/bairro, pets resumidos (nome/espécie/idade) |\n| `tutor.atualizado` | Cadastro do responsável legal atualizado | mesmos dados de `tutor.criado` |\n| `paciente.criado` | Pet cadastrado | nome, espécie, raça, nascimento, responsável legal vinculado |\n| `atendimento.concluido` | Atendimento concluído | pet, responsável legal, tipo de atendimento, retorno sugerido |\n| `retorno.registrado` | Retorno registrado sobre um atendimento | atendimento de origem, conduta, pet, responsável legal |\n| `aniversario.pet` | Aniversário do pet (diário) | pet, idade, responsável legal (nome/telefone/e-mail) |\n\n#### Saúde\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `vacina.aplicada` | Vacina/ação de saúde aplicada | vacina, data, próxima dose, pet, responsável legal |\n| `vacina.vencendo` | Vacina com reforço próximo (diário) | vacina, data prevista, pet, responsável legal |\n| `exame.anexado` | Resultado de exame anexado | tipo de exame, pet, URL de download com expiração |\n| `pesagem.registrada` | Pesagem registrada | peso canônico, data, pet |\n\n#### CRM\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `lead.criado` | Lead novo no CRM (formulário de entrada, contato pelo perfil no Hub ou cadastro pela equipe) | nome, telefone, e-mail, origem, etapa e a campanha do link (origem, meio e nome) |\n| `lead.campanha.boas-vindas` | Boas-vindas da campanha enviadas pela integração (aba Campanha da ficha do lead) | o lead (os dados de `lead.criado`), a mensagem pronta, os links e quem enviou |\n| `lead.campanha.triagem` | Triagem da campanha enviada pela integração (aba Campanha da ficha do lead) | o lead (os dados de `lead.criado`), a mensagem pronta, os links e quem enviou |\n| `lead.campanha.tratamento` | Última etapa da campanha (tratamento; na clínica, agendamento) enviada pela integração | o lead (os dados de `lead.criado`), a mensagem pronta, os links e quem enviou |\n\n#### Agenda\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `calendario.criado` | Calendário/agenda criado | título, usuário |\n| `agendamento.criado` | Agendamento criado | data/hora com timezone, profissional, serviço, pet, responsável legal, origem |\n| `agendamento.remarcado` | Agendamento remarcado | dados do agendamento + data anterior |\n| `agendamento.cancelado` | Agendamento cancelado | dados do agendamento |\n| `agendamento.solicitado` | Solicitação da agenda pública (aguardando aprovação) | dados do agendamento + status pendente |\n\n#### Parceiros\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `coleta.solicitada` | Ordem de coleta enviada a laboratório | exames pedidos, pet, clínica solicitante |\n| `coleta.atendida` | Ordem de coleta respondida | exames, status, laboratório |\n| `encaminhamento.emitido` | Encaminhamento ao parceiro emitido no orçamento | código, origem, campanha, parceiro, unidade sugerida, clínica, veterinário (nome e CRMV), situação, datas |\n| `encaminhamento.lido` | Link do encaminhamento aberto pelo responsável legal | mesmos dados de `encaminhamento.emitido` |\n| `encaminhamento.utilizado` | Retirada confirmada pelo parceiro | mesmos dados de `encaminhamento.emitido` + data da baixa e se veio pela chave de API |\n| `encaminhamento.cancelado` | Encaminhamento cancelado (venda desfeita ou item fora do orçamento) | mesmos dados de `encaminhamento.emitido` |\n\n#### Documentos\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `documento.emitido` | Documento emitido | tipo, título, pet, responsável legal, URL do PDF, flag geradoComIa |\n| `documento.assinado` | Documento assinado eletronicamente | documento + data da assinatura |\n\n#### Internamento\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `internacao.iniciada` | Internação iniciada | leito, pet, motivo |\n| `alta.registrada` | Alta registrada | pet, período, desfecho |\n\n#### Configuração\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `perfil.configurado` | Perfil da clínica configurado (MAPA + CNPJ + endereço) | registro MAPA, CNPJ, endereço |\n\n#### Estoque\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `estoque.baixo` | Produto atingiu o estoque mínimo (ponto de reposição) | produto (id/nome), saldo atual, estoque mínimo |\n| `estoque.entrada` | Entrada de mercadoria registrada | produto, quantidade, custo unitário, lote/validade, saldo resultante |\n\n#### Atendimento\n\n| Evento | Quando | O que trafega |\n| --- | --- | --- |\n| `ficha.finalizada` | Ficha de atendimento finalizada pelo veterinário | ficha (nome), atendimento, pet, responsável legal, momento da finalização |\n| `teleconsulta.retornada` | Teleconsulta encerrada e gravação disponível | atendimento, pet, links de vídeo/áudio/transcrição com expiração, início e fim da sessão |\n| `transcricao.concluida` | Transcrição do áudio do atendimento concluída | atendimento, pet, situação da transcrição |",
    "contact": {
      "name": "Desenvolvimento",
      "url": "https://atendevet.com.br",
      "email": "contato@atendevet.com.br"
    },
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.atendevet.app"
    }
  ],
  "paths": {
    "/cliente/{clienteId}": {
      "get": {
        "tags": [
          "Clientes"
        ],
        "summary": "Obter cliente por id",
        "description": "Ficha do cliente (o responsável legal) com os pacientes dele. Id de outra clínica ou inexistente responde 400.\n\nEscopo da chave: `atendimento.cliente.ler` (Consultar responsáveis legais e endereços).",
        "operationId": "Cliente_ClientePorId",
        "parameters": [
          {
            "name": "clienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteDetalheResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/cliente/{clienteId}/endereco": {
      "get": {
        "tags": [
          "Clientes"
        ],
        "summary": "Obter endereço do cliente",
        "description": "Endereço cadastrado do cliente, pelo id dele.\n\nEscopo da chave: `atendimento.cliente.ler` (Consultar responsáveis legais e endereços).",
        "operationId": "Cliente_EnderecoPorClienteId",
        "parameters": [
          {
            "name": "clienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnderecoResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/cliente/enderecos": {
      "get": {
        "tags": [
          "Clientes"
        ],
        "summary": "Listar endereços de vários clientes",
        "description": "Endereços de vários clientes numa chamada. Repita o parâmetro: clientesIds=1&clientesIds=2.\n\nEscopo da chave: `atendimento.cliente.ler` (Consultar responsáveis legais e endereços) ou `atendimento.calendario.ler` (Consultar a agenda).",
        "operationId": "Cliente_EnderecosPorClientesId",
        "parameters": [
          {
            "name": "clientesIds",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "integer",
                "format": "int64"
              }
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnderecoResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/cliente/search": {
      "get": {
        "tags": [
          "Clientes"
        ],
        "summary": "Pesquisar clientes",
        "description": "Busca por nome, documento, e-mail, nome ou tag do pet e id externo (o código do sistema anterior, comparado inteiro). Devolve no máximo 50 clientes (25 sem texto de busca), em ordem alfabética. Nesta rota, DateIn, DateEnd, Page e PageSize são ignorados.\n\nEscopo da chave: `atendimento.cliente.ler` (Consultar responsáveis legais e endereços).",
        "operationId": "Cliente_PesquisarSync",
        "parameters": [
          {
            "name": "Param",
            "in": "query",
            "description": "Texto procurado",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Active",
            "in": "query",
            "description": "true = só cadastros ativos; false = só os inativos. Padrão: false, então envie Active=true na busca comum",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "DateIn",
            "in": "query",
            "description": "Primeiro dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateEnd",
            "in": "query",
            "description": "Último dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "Page",
            "in": "query",
            "description": "Página, a partir de 1",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Itens por página (padrão 10)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ClienteResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/cliente/search/paginated": {
      "get": {
        "tags": [
          "Clientes"
        ],
        "summary": "Pesquisar clientes (paginado)",
        "description": "Busca por nome, documento, e-mail ou nome do pet, em páginas. sumidos=true traz só os clientes sem venda, ficha ou agendamento há 6 a 18 meses. comPetExcluido=true, junto com Active=false, traz também o cliente ativo com pelo menos um pet excluído, só com os pets excluídos dele. Nesta rota, DateIn e DateEnd são ignorados.\n\nEscopo da chave: `atendimento.cliente.ler` (Consultar responsáveis legais e endereços).",
        "operationId": "Cliente_PesquisarPaginado",
        "parameters": [
          {
            "name": "Param",
            "in": "query",
            "description": "Texto procurado",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Active",
            "in": "query",
            "description": "true = só cadastros ativos; false = só os inativos. Padrão: false, então envie Active=true na busca comum",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "DateIn",
            "in": "query",
            "description": "Primeiro dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateEnd",
            "in": "query",
            "description": "Último dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "Page",
            "in": "query",
            "description": "Página, a partir de 1",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Itens por página (padrão 10)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "sumidos",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "comPetExcluido",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClienteResponsePaginado"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/crm/gestao": {
      "get": {
        "tags": [
          "CRM — gestão"
        ],
        "summary": "Listar leads (paginado)",
        "description": "Leads do CRM da clínica, com filtros, até 100 por página.\n\nEscopo da chave: `parceiros.hub.ler` (Ler os contatos do CRM).",
        "operationId": "CrmGestao_Listar",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Estágio do funil (EmContato, Qualificado...; o número também vale).",
            "schema": {
              "$ref": "#/components/schemas/EnumLeadStatus"
            }
          },
          {
            "name": "tipo",
            "in": "query",
            "description": "Tipo do contato.",
            "schema": {
              "$ref": "#/components/schemas/EnumLeadTipo"
            }
          },
          {
            "name": "busca",
            "in": "query",
            "description": "Texto procurado no nome, na empresa, no e-mail, no telefone e na origem.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "origem",
            "in": "query",
            "description": "Começo da origem: 'public-contact' traz o formulário inteiro, 'public-contact:instagram' só esse canal.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Página, a partir de 1.",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Leads por página: padrão 20, máximo 100.",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "sortField",
            "in": "query",
            "description": "Ordenação: nome, empresa, email, status, tipo, criadoEm (padrão), segmento, telefone ou proximaAcao.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortDirection",
            "in": "query",
            "description": "asc ou desc (padrão).",
            "schema": {
              "type": "string",
              "default": "desc"
            }
          },
          {
            "name": "criadoDe",
            "in": "query",
            "description": "Primeiro dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "criadoAte",
            "in": "query",
            "description": "Último dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "responsavelId",
            "in": "query",
            "description": "Id do usuário dono do lead; quando vem, semResponsavel é ignorado.",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "semResponsavel",
            "in": "query",
            "description": "true = só leads sem dono.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "segmento",
            "in": "query",
            "description": "Segmento comercial do contato.",
            "schema": {
              "$ref": "#/components/schemas/EnumLeadSegmento"
            }
          },
          {
            "name": "motivoDescarte",
            "in": "query",
            "description": "Por que o lead saiu do funil (com status=Descartado).",
            "schema": {
              "$ref": "#/components/schemas/EnumLeadMotivoDescarte"
            }
          },
          {
            "name": "proximaAcaoAte",
            "in": "query",
            "description": "Último dia da próxima ação combinada (aaaa-mm-dd), incluído.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "apenasComProximaAcao",
            "in": "query",
            "description": "true = só leads com próxima ação combinada.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "apenasAtrasados",
            "in": "query",
            "description": "true = só leads com a próxima ação vencida.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "jaEhUsuario",
            "in": "query",
            "description": "Só no CRM da Atendevet: true = quem já tem conta na plataforma. Na clínica, é ignorado.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "agruparPor",
            "in": "query",
            "description": "Junta os leads repetidos pelo mesmo nome, e-mail ou telefone.",
            "schema": {
              "$ref": "#/components/schemas/EnumLeadAgrupamento"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "description": "Uma tag do lead, comparada inteira.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "temperaturaDe",
            "in": "query",
            "description": "Temperatura mínima, de 0 a 100 (frio abaixo de 40, morno de 40 a 69, quente de 70 em diante), incluída.",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "temperaturaAte",
            "in": "query",
            "description": "Temperatura máxima, de 0 a 100, incluída.",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "campanha",
            "in": "query",
            "description": "Nome da campanha (utm_campaign do link), comparado inteiro.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "saudeDaConta",
            "in": "query",
            "description": "Só no CRM da Atendevet: faixa de saúde da conta do lead. Na clínica, é ignorado.",
            "schema": {
              "$ref": "#/components/schemas/EnumBandaSaude"
            }
          },
          {
            "name": "planoDaConta",
            "in": "query",
            "description": "Só no CRM da Atendevet: plano da conta do lead. Na clínica, é ignorado.",
            "schema": {
              "$ref": "#/components/schemas/EnumPlanoTipo"
            }
          },
          {
            "name": "cobranca",
            "in": "query",
            "description": "Só no CRM da Atendevet: situação de cobrança da conta do lead. Na clínica, é ignorado.",
            "schema": {
              "$ref": "#/components/schemas/EnumSituacaoCobranca"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadResponsePaginado"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/crm/gestao/funil": {
      "get": {
        "tags": [
          "CRM — gestão"
        ],
        "summary": "Contar leads por estágio do funil",
        "description": "Quantos leads há em cada estágio, mais os cortes da fila: atrasados (próxima ação vencida, fora do total) e para hoje. Respeita canal, campanha, período e dono; não recorta por estágio, tipo, segmento nem busca.\n\nEscopo da chave: `parceiros.hub.ler` (Ler os contatos do CRM).",
        "operationId": "CrmGestao_Funil",
        "parameters": [
          {
            "name": "origem",
            "in": "query",
            "description": "Começo da origem: 'public-contact' traz o formulário inteiro, 'public-contact:instagram' só esse canal.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "criadoDe",
            "in": "query",
            "description": "Primeiro dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "criadoAte",
            "in": "query",
            "description": "Último dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "responsavelId",
            "in": "query",
            "description": "Id do usuário dono do lead; quando vem, semResponsavel é ignorado.",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "semResponsavel",
            "in": "query",
            "description": "true = só leads sem dono.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "tag",
            "in": "query",
            "description": "Uma tag do lead, comparada inteira.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campanha",
            "in": "query",
            "description": "Nome da campanha (utm_campaign do link), comparado inteiro.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadFunilResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/crm/gestao/funil/canais": {
      "get": {
        "tags": [
          "CRM — gestão"
        ],
        "summary": "Contar leads por canal, campanha e segmento",
        "description": "De onde vêm os leads e até onde chegaram: por canal de origem, por campanha (utm_campaign do link) e por segmento. Respeita período e dono; não recorta por canal nem por campanha, para comparar todos.\n\nEscopo da chave: `parceiros.hub.ler` (Ler os contatos do CRM).",
        "operationId": "CrmGestao_Canais",
        "parameters": [
          {
            "name": "criadoDe",
            "in": "query",
            "description": "Primeiro dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "criadoAte",
            "in": "query",
            "description": "Último dia de entrada no CRM (aaaa-mm-dd), incluído, no fuso do cabeçalho X-Timezone.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "responsavelId",
            "in": "query",
            "description": "Id do usuário dono do lead; quando vem, semResponsavel é ignorado.",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "semResponsavel",
            "in": "query",
            "description": "true = só leads sem dono.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "tag",
            "in": "query",
            "description": "Uma tag do lead, comparada inteira.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadCanaisResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/crm/gestao/{id}": {
      "get": {
        "tags": [
          "CRM — gestão"
        ],
        "summary": "Obter lead por id",
        "description": "Ficha do lead.\n\nEscopo da chave: `parceiros.hub.ler` (Ler os contatos do CRM).",
        "operationId": "CrmGestao_Obter",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/documento/modelo": {
      "put": {
        "tags": [
          "Documentos"
        ],
        "summary": "Atualizar modelo de documento",
        "description": "Atualiza um modelo de documento da clínica. Modelos da plataforma (publico = true) são somente leitura: servem para emitir, mas não podem ser editados (400).\n\nEscopo da chave: `atendimento.prescricao.salvar` (Editar documentos e modelos).",
        "operationId": "Documento_AtualizarModelo",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceitaTemplateRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/ReceitaTemplateRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/ReceitaTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo."
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso"
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      },
      "get": {
        "tags": [
          "Documentos"
        ],
        "summary": "Listar modelos de documento",
        "description": "Modelos da clínica e da plataforma de um tipo (tipo; 0 = Receita), filtrados por parte do nome (param) e por ativo (padrão true), em ordem alfabética.\n\nEscopo da chave: `atendimento.prescricao.ler` (Consultar documentos e modelos).",
        "operationId": "Documento_PesquisarModelos",
        "parameters": [
          {
            "name": "tipo",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/EnumDocumentoTipo"
            }
          },
          {
            "name": "param",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ativo",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReceitaModeloResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/documento/modelo/paginado": {
      "get": {
        "tags": [
          "Documentos"
        ],
        "summary": "Listar modelos de documento (paginado)",
        "description": "A mesma lista, em páginas. origem recorta entre os modelos da plataforma (Sistema) e os da clínica (Personalizado); sem ela, vêm os dois. O conteúdo do modelo não vem nesta rota: para ele, use /documento/modelo/{modeloId}.\n\nEscopo da chave: `atendimento.prescricao.ler` (Consultar documentos e modelos).",
        "operationId": "Documento_PesquisarModelosPaginado",
        "parameters": [
          {
            "name": "tipo",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/EnumDocumentoTipo"
            }
          },
          {
            "name": "param",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ativo",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          },
          {
            "name": "origem",
            "in": "query",
            "description": "Quais registros listar: os da plataforma e os da clínica (padrão), só os da clínica ou só os da plataforma.",
            "schema": {
              "$ref": "#/components/schemas/EnumOrigemRegistro"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceitaModeloResponsePaginado"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/documento/modelo/{modeloId}": {
      "get": {
        "tags": [
          "Documentos"
        ],
        "summary": "Obter modelo de documento por id",
        "description": "Modelo de documento com o conteúdo completo.\n\nEscopo da chave: `atendimento.prescricao.ler` (Consultar documentos e modelos).",
        "operationId": "Documento_PorId",
        "parameters": [
          {
            "name": "modeloId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReceitaModeloResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      },
      "delete": {
        "tags": [
          "Documentos"
        ],
        "summary": "Inativar modelo de documento",
        "description": "Inativa um modelo da clínica; dá para restaurar depois. Modelos da plataforma (publico = true) não podem ser removidos (400).\n\nEscopo da chave: `atendimento.prescricao.excluir` (Remover e restaurar modelos).",
        "operationId": "Documento_RemoverModelo",
        "parameters": [
          {
            "name": "modeloId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo."
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso"
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/documento/modelo/{modeloId}/restaurar": {
      "patch": {
        "tags": [
          "Documentos"
        ],
        "summary": "Restaurar modelo de documento",
        "description": "Reativa um modelo da clínica que foi inativado. Modelos da plataforma (publico = true) não podem ser alterados (400).\n\nEscopo da chave: `atendimento.prescricao.excluir` (Remover e restaurar modelos).",
        "operationId": "Documento_RestaurarModelo",
        "parameters": [
          {
            "name": "modeloId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo."
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso"
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/documento/assinatura/{idExterno}": {
      "get": {
        "tags": [
          "Documentos"
        ],
        "summary": "Obter situação da assinatura",
        "description": "Situação da assinatura de um documento enviado ao Autentique, pelo id externo dele.\n\nEscopo da chave: `atendimento.prescricao.ler` (Consultar documentos e modelos) ou `parceiros.hub.coleta.solicitar`.",
        "operationId": "Documento_ObterStatusAssinatura",
        "parameters": [
          {
            "name": "idExterno",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentoAssinaturaStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Não encontrado nesta clínica."
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/encaminhamento/parceiro/recentes": {
      "get": {
        "tags": [
          "Encaminhamentos ao parceiro"
        ],
        "summary": "Listar encaminhamentos recentes do parceiro",
        "description": "Os encaminhamentos mais recentes recebidos pelas filiais do parceiro, com a situação de cada um.\n\nEscopo da chave: `parceiros.hub.perfil.salvar` (Conferir e confirmar retiradas).",
        "operationId": "EncaminhamentoParceiro_ListarRecentes",
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "description": "Quantos devolver, de 1 a 100 (padrão 50).",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EncaminhamentoRecenteResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/encaminhamento/parceiro/{tokenOuCodigo}": {
      "get": {
        "tags": [
          "Encaminhamentos ao parceiro"
        ],
        "summary": "Obter encaminhamento para conferência",
        "description": "Pelo token do QR ou pelo código curto, só do parceiro dono. Além do que a página pública mostra, traz a clínica, o veterinário (nome e CRMV), o primeiro nome do responsável legal, o nome do pet, o CPF mascarado e se pode confirmar. Outro parceiro ou código inexistente responde 404.\n\nEscopo da chave: `parceiros.hub.perfil.salvar` (Conferir e confirmar retiradas).",
        "operationId": "EncaminhamentoParceiro_ObterParaParceiro",
        "parameters": [
          {
            "name": "tokenOuCodigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EncaminhamentoParceiroVisaoResponse"
                }
              }
            }
          },
          "404": {
            "description": "Não encontrado nesta clínica."
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/encaminhamento/{codigo}/confirmar": {
      "post": {
        "tags": [
          "Encaminhamentos ao parceiro"
        ],
        "summary": "Confirmar retirada do encaminhamento",
        "description": "Baixa do parceiro dono pelo código curto: marca como utilizado e avisa a clínica e o parceiro (webhook encaminhamento.utilizado). Confirmar de novo devolve o mesmo estado, sem erro. Orçamento não aprovado, vencido ou cancelado responde 400 com o motivo.\n\nEscopo da chave: `parceiros.hub.perfil.salvar` (Conferir e confirmar retiradas).",
        "operationId": "EncaminhamentoParceiro_Confirmar",
        "parameters": [
          {
            "name": "codigo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EncaminhamentoParceiroVisaoResponse"
                }
              }
            }
          },
          "404": {
            "description": "Não encontrado nesta clínica."
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          }
        }
      }
    },
    "/integracao/turnos": {
      "put": {
        "tags": [
          "Integrações — plantões"
        ],
        "summary": "Gravar plantões de sistema externo",
        "description": "Cria ou atualiza plantões pelo externoId, até 500 por chamada: o plantão entra publicado, e cancelado = true o retira da escala. Profissional pelo e-mail (ativo na clínica da chave) e local pelo código (ativo). Horário local da clínica, sem fuso, até 24 h, em grade de 15 min. Item recusado volta em erros sem impedir os outros; repetir a mesma chamada não muda nada.\n\nEscopo da chave: `atendimento.calendario.equipe` (Integrar a escala de plantões).",
        "operationId": "IntegracaoTurno_Integrar",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TurnoIntegracaoItem"
                }
              }
            },
            "text/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TurnoIntegracaoItem"
                }
              }
            },
            "application/*+json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TurnoIntegracaoItem"
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegracaoTurnosResponse"
                }
              }
            }
          }
        }
      }
    },
    "/nota/geradas": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Listar notas",
        "description": "Orçamentos e vendas da clínica, as 100 mais recentes do filtro. O titular vê as da clínica e filtra por qualquer emissorId; o colaborador vê só a própria produção (notas que emitiu ou em que executou item), e o emissorId de outro é ignorado. aReceber=true traz só as vendas aprovadas (Contratada ou Processando) ainda não pagas por inteiro; clienteId restringe às vendas do responsável legal (como paciente, pet num item, evento ou cobrança recorrente). dataInicio e dataFim filtram pelo dia de criação da nota, em UTC, e só valem juntas.\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_MinhasNotas",
        "parameters": [
          {
            "name": "emissorId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "dataInicio",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dataFim",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "nota",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "porProcessados",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aReceber",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "clienteId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NotaResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/geradas/kanban": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Listar notas agrupadas por status",
        "description": "A primeira página de cada status, na ordem do ciclo da venda, com o total real de cada um. Mesma regra de visibilidade de /nota/geradas.\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_MinhasNotasKanban",
        "parameters": [
          {
            "name": "emissorId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "dataInicio",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dataFim",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "nota",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "porColuna",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotaResponseKanban"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/geradas/kanban/coluna": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Listar notas de um status (paginado)",
        "description": "A próxima página de um status. Mesma regra de visibilidade de /nota/geradas.\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_MinhasNotasColuna",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "status da nota de serviço",
            "schema": {
              "$ref": "#/components/schemas/EnumNotaStatus"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "emissorId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "dataInicio",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dataFim",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "nota",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotaResponsePaginado"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/{notaId}/servicos": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Obter itens da nota",
        "description": "Serviços e produtos da nota. Pela chave de API, a venda traz nome, CPF, endereço e pet do cliente; o escopo financeiro.ler sozinho dá 403 (os números das vendas estão em /relatorio/venda/resumo e /relatorio/venda/cliente).\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_ObterCatalogoPorId",
        "parameters": [
          {
            "name": "notaId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotaServicoResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/clientes/{clienteId}": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Listar notas do cliente",
        "description": "Notas vinculadas ao cliente, pelo id dele.\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_NotasPorCliente",
        "parameters": [
          {
            "name": "clienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NotaResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/{notaId}": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Obter nota por id",
        "description": "Nota com os itens e os pagamentos. Pela chave de API, a venda traz nome, CPF, endereço e pet do cliente; o escopo financeiro.ler sozinho dá 403 (os números das vendas estão em /relatorio/venda/resumo e /relatorio/venda/cliente).\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_NotaPorId",
        "parameters": [
          {
            "name": "notaId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotaResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/nota/emissores/{emissorId}": {
      "get": {
        "tags": [
          "Notas e vendas"
        ],
        "summary": "Listar notas do emissor",
        "description": "Notas emitidas pelo emissor (id do usuário); o colaborador que pede as de outro emissor recebe as dele.\n\nEscopo da chave: `atendimento.nota.ler` (Consultar orçamentos) ou `atendimento.nota.salvar` (Propor orçamentos).",
        "operationId": "Nota_NotasPorEmissor",
        "parameters": [
          {
            "name": "emissorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "dateStart",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "dateEnd",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NotaResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Listar pacientes atendidos recentemente",
        "description": "Os 10 pacientes com registro mais recente no prontuário da clínica. Para buscar ou listar todos, use /paciente/search ou /cliente/search/paginated.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)).",
        "operationId": "Paciente_Pacientes",
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PacienteResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/{pacienteId}": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Obter paciente por id",
        "description": "Ficha do paciente da clínica.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)).",
        "operationId": "Paciente_PacientePorId",
        "parameters": [
          {
            "name": "pacienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PacienteDetalheResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/{pacienteId}/resume": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Listar histórico de ações do paciente",
        "description": "Ações registradas no histórico do paciente.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)).",
        "operationId": "Paciente_HistoricoPorPacienteId",
        "parameters": [
          {
            "name": "pacienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PacienteHistoricoResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/search": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Pesquisar pacientes",
        "description": "Busca pelo nome do pet ou pelo nome, CPF ou RG do responsável legal, com filtro pela data de cadastro (DateIn e DateEnd). Devolve no máximo 15 pacientes (10 sem texto de busca), do cadastro mais antigo para o mais novo. Nesta rota, Page e PageSize são ignorados.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)).",
        "operationId": "Paciente_PesquisarSync",
        "parameters": [
          {
            "name": "Param",
            "in": "query",
            "description": "Texto procurado",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Active",
            "in": "query",
            "description": "true = só cadastros ativos; false = só os inativos. Padrão: false, então envie Active=true na busca comum",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "DateIn",
            "in": "query",
            "description": "Primeiro dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "DateEnd",
            "in": "query",
            "description": "Último dia do cadastro, incluído (só nas rotas que dizem usar)",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "Page",
            "in": "query",
            "description": "Página, a partir de 1",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "description": "Itens por página (padrão 10)",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PacienteResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/pesagem/{pacienteId}": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Listar pesagens do paciente",
        "description": "Pesagens registradas do paciente.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)) ou `atendimento.saude.ler` (Consultar carteira de saúde).",
        "operationId": "Paciente_ListarPesagem",
        "parameters": [
          {
            "name": "pacienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PesagemResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/peso/historico/{pacienteId}": {
      "get": {
        "tags": [
          "Pacientes"
        ],
        "summary": "Obter histórico de peso do paciente",
        "description": "Linha do tempo do peso (kg), juntando pesagens, fichas de atendimento e internação.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)) ou `atendimento.prontuario.ler` (Consultar prontuário e internações).",
        "operationId": "Paciente_HistoricoPeso",
        "parameters": [
          {
            "name": "pacienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoricoPesoResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/antecedentes/{pacienteId}": {
      "get": {
        "tags": [
          "Pacientes — antecedentes"
        ],
        "summary": "Obter antecedentes do paciente",
        "description": "Antecedentes pessoais e familiares e os alertas de segurança: alergias e reações vigentes e medicamentos em uso.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)) ou `atendimento.prontuario.ler` (Consultar prontuário e internações).",
        "operationId": "Antecedente_PorPaciente",
        "parameters": [
          {
            "name": "pacienteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AntecedentesPacienteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/paciente/antecedentes/catalogo": {
      "get": {
        "tags": [
          "Pacientes — antecedentes"
        ],
        "summary": "Listar sugestões de antecedentes",
        "description": "Sugestões para preencher antecedentes, por categoria e vertical: as da plataforma e as da clínica. busca filtra pelo nome.\n\nEscopo da chave: `atendimento.paciente.ler` (Consultar pacientes (pets)) ou `atendimento.prontuario.ler` (Consultar prontuário e internações).",
        "operationId": "Antecedente_Catalogo",
        "parameters": [
          {
            "name": "categoria",
            "in": "query",
            "description": "Categoria de um antecedente pessoal do paciente. Vale para as duas verticais: o que muda\nentre veterinária e humana é o catálogo de sugestões, não a categoria.",
            "schema": {
              "$ref": "#/components/schemas/EnumAntecedenteCategoria"
            }
          },
          {
            "name": "vertical",
            "in": "query",
            "description": "Em que vertical o item do catálogo faz sentido: veterinária, saúde humana ou as duas.",
            "schema": {
              "$ref": "#/components/schemas/EnumVerticalCatalogo"
            }
          },
          {
            "name": "busca",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AntecedenteCatalogoResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          }
        }
      }
    },
    "/relatorio/venda/resumo": {
      "get": {
        "tags": [
          "Relatórios"
        ],
        "summary": "Obter resumo de vendas do período",
        "description": "Total das vendas do período, para conferir com os números de outro sistema. total e quantidade somam só a venda firme: Contratada (aprovada, sem pagamento), Processando (paga em parte) e Processada (quitada), a mesma régua do relatório financeiro. pago é a parte do total já registrada como pagamento, e emAberto o que falta receber. porStatus traz sempre os seis status, inclusive Aprovando (orçamento), Cancelada e Estornada, que ficam fora do total (entraNoTotal). localId (opcional; ausente ou 0 = clínica inteira) recorta pela unidade, com os espaços dela: a venda conta no local do evento, senão no da nota. Só números: nenhum nome, documento, endereço ou pet, nem custo, lucro, taxa ou imposto. O alcance é o de quem criou a chave: o titular vê a clínica inteira; o colaborador, só as vendas que emitiu ou em que atendeu. Até 60 chamadas por minuto por chave (no app, por usuário), somando as duas rotas de venda. inicio e fim são dias (aaaa-mm-dd) entre 2000-01-01 e 2099-12-31, os dois inclusos, em até 366 dias (fora disso, 400), no fuso do cabeçalho X-Timezone (IANA, ex.: America/Sao_Paulo; sem ele, Brasília). A venda conta no dia do atendimento (o do agendamento dela; sem agendamento, o dia em que foi criada), a mesma competência de toda tela de venda e da DRE.\n\nEscopo da chave: `financeiro.ler` (Consultar indicadores financeiros).",
        "operationId": "Relatorio_ResumoDeVendas",
        "parameters": [
          {
            "name": "inicio",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "fim",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "localId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VendasDoPeriodoResponse"
                }
              }
            }
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          }
        }
      }
    },
    "/relatorio/venda/cliente": {
      "get": {
        "tags": [
          "Relatórios"
        ],
        "summary": "Listar vendas do período por cliente",
        "description": "Vendas firmes do período por responsável legal, só com o id do cliente (o mesmo de /cliente/{id}): valor é o faturamento do relatório financeiro por cliente, quantidade as vendas e ultimaVendaEm a mais recente do período. Serve para saber se uma venda já foi registrada sem abrir a ficha do cliente. clienteIds (opcional, repetível: clienteIds=1&clienteIds=2, até 200; acima, 400) limita aos clientes pedidos; cliente sem venda no período não vem. Sem o filtro, as vendas sem responsável legal vinculado vêm numa linha com clienteId nulo, e a soma das linhas fecha com o total de /relatorio/venda/resumo: venda de dois responsáveis legais conta para os dois, com o valor rateado pelos itens, e o arredondamento pode deixar centavos de diferença. localId (opcional; ausente ou 0 = clínica inteira) recorta pela unidade, com os espaços dela: a venda conta no local do evento, senão no da nota. Só números: nenhum nome, documento, endereço ou pet, nem custo, lucro, taxa ou imposto. O alcance é o de quem criou a chave: o titular vê a clínica inteira; o colaborador, só as vendas que emitiu ou em que atendeu. Até 60 chamadas por minuto por chave (no app, por usuário), somando as duas rotas de venda. inicio e fim são dias (aaaa-mm-dd) entre 2000-01-01 e 2099-12-31, os dois inclusos, em até 366 dias (fora disso, 400), no fuso do cabeçalho X-Timezone (IANA, ex.: America/Sao_Paulo; sem ele, Brasília). A venda conta no dia do atendimento (o do agendamento dela; sem agendamento, o dia em que foi criada), a mesma competência de toda tela de venda e da DRE.\n\nEscopo da chave: `financeiro.ler` (Consultar indicadores financeiros).",
        "operationId": "Relatorio_VendasPorCliente",
        "parameters": [
          {
            "name": "inicio",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "fim",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "clienteIds",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          {
            "name": "localId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Pedido recusado: o corpo traz a lista de mensagens (key = campo, message = motivo). Parâmetro malformado (data inválida, valor fora da lista) volta no formato de validação padrão, com os erros por campo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Erro interno; o corpo traz a mensagem.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas por minuto excedido; tente de novo em instantes."
          },
          "200": {
            "description": "Sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VendasDoClienteResponse"
                  }
                }
              }
            }
          },
          "403": {
            "description": "A chave não tem o escopo exigido, ou a assinatura da clínica tem pendência (o motivo vem em error_description)."
          },
          "401": {
            "description": "Chave de API ausente, inválida, revogada ou vencida."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AntecedenteCatalogoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "categoria": {
            "$ref": "#/components/schemas/EnumAntecedenteCategoria"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "vertical": {
            "$ref": "#/components/schemas/EnumVerticalCatalogo"
          },
          "publico": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "AntecedenteFamiliarResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "pacienteId": {
            "type": "integer",
            "format": "int64"
          },
          "parentesco": {
            "$ref": "#/components/schemas/EnumParentesco"
          },
          "condicao": {
            "type": "string",
            "nullable": true
          },
          "idadeNoDiagnostico": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detalhe": {
            "type": "string",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "AntecedenteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "pacienteId": {
            "type": "integer",
            "format": "int64"
          },
          "categoria": {
            "$ref": "#/components/schemas/EnumAntecedenteCategoria"
          },
          "titulo": {
            "type": "string",
            "nullable": true
          },
          "detalhe": {
            "type": "string",
            "nullable": true
          },
          "inicio": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fim": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "gravidade": {
            "$ref": "#/components/schemas/EnumAntecedenteGravidade"
          },
          "origem": {
            "$ref": "#/components/schemas/EnumAntecedenteOrigem"
          },
          "anamneseId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "vigente": {
            "type": "boolean"
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "AntecedentesPacienteResponse": {
        "type": "object",
        "properties": {
          "pessoais": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AntecedenteResponse"
            },
            "nullable": true
          },
          "familiares": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AntecedenteFamiliarResponse"
            },
            "nullable": true
          },
          "alertasSeguranca": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AntecedenteResponse"
            },
            "description": "Alergias e reações adversas vigentes.",
            "nullable": true
          },
          "medicamentosEmUso": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AntecedenteResponse"
            },
            "description": "Medicamentos em uso vigentes.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Antecedentes do paciente numa chamada: pessoais, familiares e os alertas de segurança."
      },
      "CarteiraResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Numero de indentificação da carteira",
            "format": "int64"
          },
          "fiv": {
            "type": "boolean",
            "description": "resultado do teste de Fiv — null quando não testado",
            "nullable": true
          },
          "felv": {
            "type": "boolean",
            "description": "resultado do teste de Felv — null quando não testado",
            "nullable": true
          },
          "pacienteId": {
            "type": "integer",
            "description": "Id do paciente para conexão com a carteira",
            "format": "int64"
          },
          "aniversario": {
            "type": "string",
            "description": "Data de aniversario do paciente",
            "nullable": true
          },
          "medicoResponsavel": {
            "type": "string",
            "description": "Nome do Medico responsavel pelo paciente",
            "nullable": true
          },
          "nomeComercial": {
            "type": "string",
            "description": "Nome comercial do Medico",
            "nullable": true
          },
          "crmv": {
            "type": "string",
            "description": "CRMV do Medico responsavel",
            "nullable": true
          },
          "peso": {
            "type": "string",
            "description": "Peso do paciente",
            "nullable": true
          },
          "qntDocumentos": {
            "type": "integer",
            "description": "Quantidade de documentos anexado na carteira",
            "format": "int32"
          },
          "ehFelino": {
            "type": "boolean",
            "description": "Paciente é da espécie felina (via sinônimos de espécie). Usado para exibir o diagnóstico\nFIV/FeLV apenas quando faz sentido (retrovírus felinos)."
          }
        },
        "additionalProperties": false
      },
      "CatalogoNotaResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "servicoId": {
            "type": "integer",
            "format": "int64"
          },
          "quantidade": {
            "type": "integer",
            "format": "int32"
          },
          "servico": {
            "type": "string",
            "nullable": true
          },
          "descricao": {
            "type": "string",
            "nullable": true
          },
          "organizacao": {
            "type": "string",
            "nullable": true
          },
          "usuario": {
            "type": "string",
            "nullable": true
          },
          "usuarioId": {
            "type": "integer",
            "format": "int64"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "desconto": {
            "type": "number",
            "format": "double"
          },
          "fator": {
            "$ref": "#/components/schemas/EnumDescontoFator"
          },
          "unidadeMedida": {
            "type": "string",
            "description": "Unidade em que a quantidade desta linha é contada (\"cp\", \"ml\", \"un\") — do produto do catálogo.\n            \n\nViaja no contrato porque o PDF do orçamento e do extrato é montado a partir DESTE\nresponse: sem ele, a coluna \"Qtde\" do documento imprime um número sem grandeza e o leitor\nnão distingue 2 comprimidos de 2 cartelas.",
            "nullable": true
          },
          "semBaixaEstoque": {
            "type": "boolean",
            "description": "Linha cujo estoque já saiu na origem (medicação aplicada no MAR).\n            \n\nImporta para o DOCUMENTO: nessas linhas a quantidade é o número de APLICAÇÕES, não\na quantidade do produto — o MAR baixou 3 × 0,5 cp, mas a nota cobra 3 aplicações.\nImprimir \"3 cp\" aqui seria mentir sobre o que foi consumido."
          },
          "vendaEmEmbalagem": {
            "type": "boolean",
            "description": "A quantidade desta linha conta EMBALAGENS, não unidades do saldo. Importa para o\ndocumento pelo mesmo motivo da Atendevet.Domain.Arguments.Catalogos.CatalogoNotaResponse.UnidadeMedida: \"2 cx (16 cp)\" e \"2 cp\" são\nleituras diferentes do mesmo número."
          },
          "quantidadePorEmbalagem": {
            "type": "number",
            "description": "Unidades por embalagem do produto — o que permite à tela e ao documento exibirem o equivalente.",
            "format": "double"
          },
          "loteEstoqueId": {
            "type": "integer",
            "description": "Lote escolhido para esta linha; nulo = o sistema usou o que vence primeiro.",
            "format": "int64",
            "nullable": true
          },
          "lote": {
            "type": "string",
            "description": "Rótulo do lote escolhido (\"L240115 • venc. 15/01/2027\") — rastreabilidade no documento.",
            "nullable": true
          },
          "notaServicoPacientes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaServicoPacienteResponse"
            },
            "nullable": true
          },
          "cobertura": {
            "$ref": "#/components/schemas/EnumCoberturaItem"
          },
          "convenioServicoId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "valorCoparticipacao": {
            "type": "number",
            "description": "R$ por unidade da linha, já resolvida.",
            "format": "double"
          },
          "coparticipacaoPercentual": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "coparticipacaoRecebidaPor": {
            "$ref": "#/components/schemas/EnumCoparticipacaoRecebidaPor"
          },
          "exigeAutorizacao": {
            "type": "boolean"
          },
          "codigoAutorizacao": {
            "type": "string",
            "nullable": true
          },
          "autorizacaoValidade": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "parteDoPlano": {
            "type": "number",
            "description": "O que a operadora paga nesta linha (todas as unidades).",
            "format": "double"
          }
        },
        "additionalProperties": false
      },
      "CatalogoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "ativo": {
            "type": "boolean"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "descricao": {
            "type": "string",
            "nullable": true
          },
          "usuario": {
            "type": "string",
            "nullable": true
          },
          "usuarioId": {
            "type": "integer",
            "format": "int64"
          },
          "tipo": {
            "$ref": "#/components/schemas/EnumServicoTipo"
          },
          "publicarNoHub": {
            "type": "boolean"
          },
          "duracaoMin": {
            "type": "integer",
            "description": "Duração do serviço em minutos (0 = não configurada). Serviço com duração pode ser agendado numa vaga do petshop.",
            "format": "int32"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "custo": {
            "type": "number",
            "format": "double"
          },
          "organizacaoId": {
            "type": "integer",
            "format": "int64"
          },
          "organizacaoNome": {
            "type": "string",
            "nullable": true
          },
          "parceiroNome": {
            "type": "string",
            "description": "Item que veio de campanha do Hub: parceiro de origem, para o selo na montagem do orçamento. Null nos itens da clínica.",
            "nullable": true
          },
          "parceiroLogoUrl": {
            "type": "string",
            "nullable": true
          },
          "parceiroCor": {
            "type": "string",
            "nullable": true
          },
          "selecionado": {
            "type": "boolean"
          },
          "quantidade": {
            "type": "integer",
            "format": "int32"
          },
          "taxas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServicoTaxaResponse"
            },
            "nullable": true
          },
          "desconto": {
            "type": "number",
            "format": "double"
          },
          "fator": {
            "$ref": "#/components/schemas/EnumDescontoFator"
          },
          "controlaEstoque": {
            "type": "boolean"
          },
          "controlaLote": {
            "type": "boolean"
          },
          "estoqueMinimo": {
            "type": "number",
            "format": "double"
          },
          "saldoEstoque": {
            "type": "number",
            "format": "double"
          },
          "unidadeMedida": {
            "type": "string",
            "nullable": true
          },
          "quantidadePorEmbalagem": {
            "type": "number",
            "format": "double"
          }
        },
        "additionalProperties": false
      },
      "ClienteDetalheResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "identificador único (id)",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "description": "Nome Registrado do Cliente",
            "nullable": true
          },
          "telefone": {
            "type": "string",
            "description": "Telefone Registrado do Cliente",
            "nullable": true
          },
          "telefoneContato": {
            "type": "string",
            "nullable": true
          },
          "contato": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "description": "Email Registrado do Cliente",
            "nullable": true
          },
          "emailAlternativo": {
            "type": "string",
            "description": "Email Alternativo Registrado do Cliente",
            "nullable": true
          },
          "emailAltAtivo": {
            "type": "boolean"
          },
          "ativo": {
            "type": "boolean",
            "description": "true = cadastro ativo"
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "cpf": {
            "type": "string",
            "nullable": true
          },
          "cnpj": {
            "type": "string",
            "nullable": true
          },
          "rg": {
            "type": "string",
            "description": "Rg Registrado do Cliente",
            "nullable": true
          },
          "aniversario": {
            "type": "string",
            "description": "Data de nascimento do cliente",
            "format": "date-time",
            "nullable": true
          },
          "pets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PacienteResponse"
            },
            "description": "Pets Registrado do Cliente",
            "nullable": true
          },
          "pesquisa": {
            "$ref": "#/components/schemas/EnumPesquisaTipo"
          },
          "endereco": {
            "type": "string",
            "nullable": true
          },
          "cadastroCompleto": {
            "type": "boolean",
            "description": "Termina o cadastro"
          },
          "demitidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "motivoDaDemissao": {
            "$ref": "#/components/schemas/EnumMotivoDemissao"
          },
          "observacaoDaDemissao": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ClienteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "identificador único (id)",
            "format": "int64"
          },
          "ativo": {
            "type": "boolean",
            "description": "mostra se o Cliente esta ativo"
          },
          "nome": {
            "type": "string",
            "description": "nome do Cliente",
            "nullable": true
          },
          "telefone": {
            "type": "string",
            "description": "telefone do Cliente",
            "nullable": true
          },
          "email": {
            "type": "string",
            "description": "email do Cliente",
            "nullable": true
          },
          "emailAlternativo": {
            "type": "string",
            "description": "email do Cliente",
            "nullable": true
          },
          "cpf": {
            "type": "string",
            "description": "Cpf do Cliente",
            "nullable": true
          },
          "cnpj": {
            "type": "string",
            "nullable": true
          },
          "rg": {
            "type": "string",
            "description": "Rg do Cliente",
            "nullable": true
          },
          "aniversario": {
            "type": "string",
            "description": "Aniversario do Cliente",
            "format": "date-time",
            "nullable": true
          },
          "contato": {
            "type": "string",
            "nullable": true
          },
          "contatoTelefone": {
            "type": "string",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "description": "mostra quando foi criado o perfiu do cliente",
            "format": "date-time"
          },
          "pesquisa": {
            "$ref": "#/components/schemas/EnumPesquisaTipo"
          },
          "endereco": {
            "$ref": "#/components/schemas/EnderecoResponse"
          },
          "pets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PacienteResponse"
            },
            "description": "mostra os Pets do Cliente",
            "nullable": true
          },
          "demitidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "motivoDaDemissao": {
            "$ref": "#/components/schemas/EnumMotivoDemissao"
          },
          "observacaoDaDemissao": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ClienteResponsePaginado": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClienteResponse"
            },
            "description": "Lista de itens da página atual",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de itens (sem paginação)",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "description": "Página atual (1-based)",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Quantidade de itens por página",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total de páginas disponíveis",
            "format": "int32",
            "readOnly": true
          },
          "hasNextPage": {
            "type": "boolean",
            "description": "Indica se há próxima página",
            "readOnly": true
          },
          "hasPreviousPage": {
            "type": "boolean",
            "description": "Indica se há página anterior",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Resposta paginada genérica para listagens"
      },
      "ConvenioDaNotaResponse": {
        "type": "object",
        "properties": {
          "credenciamentoId": {
            "type": "integer",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "modalidade": {
            "$ref": "#/components/schemas/EnumConvenioModalidade"
          },
          "numeroCarteirinha": {
            "type": "string",
            "nullable": true
          },
          "produtoNome": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "DocumentoAssinaturaStatusResponse": {
        "type": "object",
        "properties": {
          "assinado": {
            "type": "boolean"
          },
          "tipo": {
            "type": "string",
            "description": "Mesmo rótulo do aviso ao vivo: receita, termo, atestado, exame, guia ou anexo.",
            "nullable": true
          },
          "nomeDocumento": {
            "type": "string",
            "nullable": true
          },
          "uriAssinada": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Situação da assinatura de um documento enviado ao Autentique."
      },
      "EncaminhamentoItemResponse": {
        "type": "object",
        "properties": {
          "nome": {
            "type": "string",
            "nullable": true
          },
          "quantidade": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "EncaminhamentoMarcaResponse": {
        "type": "object",
        "properties": {
          "parceiroId": {
            "type": "integer",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "logoUrl": {
            "type": "string",
            "nullable": true
          },
          "cor": {
            "type": "string",
            "description": "Cor da marca em hexadecimal (#rgb ou #rrggbb); nula quando a filial não tem uma válida.",
            "nullable": true
          },
          "whatsApp": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Marca do parceiro no PDF e na página do QR."
      },
      "EncaminhamentoParceiroVisaoResponse": {
        "type": "object",
        "properties": {
          "codigo": {
            "type": "string",
            "nullable": true
          },
          "parceiro": {
            "$ref": "#/components/schemas/EncaminhamentoMarcaResponse"
          },
          "itens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EncaminhamentoItemResponse"
            },
            "nullable": true
          },
          "orientacao": {
            "type": "string",
            "nullable": true
          },
          "unidadeSugerida": {
            "$ref": "#/components/schemas/ParceiroUnidadeResponse"
          },
          "unidades": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ParceiroUnidadeResponse"
            },
            "description": "As demais unidades ativas da filial.",
            "nullable": true
          },
          "modo": {
            "$ref": "#/components/schemas/EnumModoRetirada"
          },
          "situacao": {
            "$ref": "#/components/schemas/EnumEncaminhamentoSituacao"
          },
          "situacaoTexto": {
            "type": "string",
            "nullable": true
          },
          "pagoNaClinica": {
            "type": "boolean"
          },
          "validoAte": {
            "type": "string",
            "format": "date-time"
          },
          "redirecionarPara": {
            "type": "string",
            "description": "Só no modo Redirecionamento e com o encaminhamento pronto: o programa do parceiro com o código.",
            "nullable": true
          },
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "campanha": {
            "type": "string",
            "nullable": true
          },
          "clinica": {
            "type": "string",
            "nullable": true
          },
          "veterinario": {
            "$ref": "#/components/schemas/EncaminhamentoVeterinarioResponse"
          },
          "responsavelLegalPrimeiroNome": {
            "type": "string",
            "nullable": true
          },
          "pacienteNome": {
            "type": "string",
            "nullable": true
          },
          "cpfMascarado": {
            "type": "string",
            "description": "\"***.456.789-**\": o balcão confere sem ver o documento inteiro.",
            "nullable": true
          },
          "podeConfirmar": {
            "type": "boolean"
          },
          "emitidoEm": {
            "type": "string",
            "format": "date-time"
          },
          "utilizadoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "O que o parceiro dono vê para conferir no balcão, além da página pública."
      },
      "EncaminhamentoRecenteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "codigo": {
            "type": "string",
            "nullable": true
          },
          "filial": {
            "type": "string",
            "nullable": true
          },
          "item": {
            "type": "string",
            "nullable": true
          },
          "clinica": {
            "type": "string",
            "nullable": true
          },
          "pacienteNome": {
            "type": "string",
            "nullable": true
          },
          "situacao": {
            "$ref": "#/components/schemas/EnumEncaminhamentoSituacao"
          },
          "situacaoTexto": {
            "type": "string",
            "nullable": true
          },
          "emitidoEm": {
            "type": "string",
            "format": "date-time"
          },
          "utilizadoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Linha da lista de retiradas do parceiro."
      },
      "EncaminhamentoVeterinarioResponse": {
        "type": "object",
        "properties": {
          "nome": {
            "type": "string",
            "nullable": true
          },
          "crmv": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "EnderecoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "identificador único (id)",
            "format": "int64"
          },
          "rua": {
            "type": "string",
            "description": "Representa a Rua do Cliente, registro no site",
            "nullable": true
          },
          "complemento": {
            "type": "string",
            "description": "Complemento da Rua ou Bairro do Cliente",
            "nullable": true
          },
          "cidade": {
            "type": "string",
            "description": "Representa a Cidade do Cliente",
            "nullable": true
          },
          "estado": {
            "type": "string",
            "description": "Representa o estado do Cliente",
            "nullable": true
          },
          "bairro": {
            "type": "string",
            "description": "Representa o Bairro do Cliente",
            "nullable": true
          },
          "clienteId": {
            "type": "integer",
            "description": "Id do cliente dono do endereço",
            "format": "int64"
          },
          "cep": {
            "type": "integer",
            "description": "Representa o Cep do Cliente",
            "format": "int32",
            "nullable": true
          },
          "numero": {
            "type": "integer",
            "description": "Representa o numero da casa do Cliente",
            "format": "int32",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "EnumAntecedenteCategoria": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8
        ],
        "type": "integer",
        "description": "Categoria de um antecedente pessoal do paciente. Vale para as duas verticais: o que muda\nentre veterinária e humana é o catálogo de sugestões, não a categoria.\n\nValores: `0` = Condicao; `1` = Cirurgia; `2` = Internacao; `3` = Alergia; `4` = MedicamentoEmUso; `5` = ReacaoAdversa; `6` = Reprodutivo; `7` = Habito; `8` = Outro.",
        "format": "int32"
      },
      "EnumAntecedenteGravidade": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Gravidade de uma alergia ou reação adversa. Só faz sentido nessas categorias.\n\nValores: `0` = Leve; `1` = Moderada; `2` = Grave.",
        "format": "int32"
      },
      "EnumAntecedenteOrigem": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "description": "Quem registrou o antecedente — a clínica confia mais no que ela mesma apurou.\n\nValores: `0` = Manual; `1` = Atendimento; `2` = Importacao; `3` = Responsavel; `4` = Copiloto.",
        "format": "int32"
      },
      "EnumBandaSaude": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "description": "Banda de saúde da conta — a fila de trabalho do time de Sucesso do Cliente.\nOrdem intencional (menor = mais crítico para atuar), exceto Onboarding que é trilha à parte.\n\nValores: `0` = Onboarding; `1` = Inativo; `2` = Risco; `3` = Atencao; `4` = Saudavel.",
        "format": "int32"
      },
      "EnumCoberturaItem": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "Quem paga a linha da venda: o responsável legal (particular) ou o convênio do paciente, pela tabela do\ncredenciamento. Particular = 0 mantém toda venda existente e todo caller sem convênio como estava.\nEspelhado no app com os mesmos números.\n\nValores: `0` = Particular; `1` = Convenio.",
        "format": "int32"
      },
      "EnumConvenioLoteStatus": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Andamento do lote de faturamento ao convênio. Espelhado no app com os mesmos números.\n\nValores: `0` = Aberto; `1` = Enviado; `2` = Pago.",
        "format": "int32"
      },
      "EnumConvenioModalidade": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Como o convênio paga a clínica. Rede: tabela do convênio, coparticipação do responsável e o resto a receber da\noperadora. Desconto (clube): tabela do convênio, o responsável paga tudo. Reembolso: venda particular; a nota só\nleva a carteirinha para o responsável pedir o ressarcimento. Espelhado no app com os mesmos números.\n\nValores: `0` = Rede; `1` = Desconto; `2` = Reembolso.",
        "format": "int32"
      },
      "EnumCoparticipacaoRecebidaPor": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "Quem recebe a coparticipação do responsável: a clínica, no caixa da venda (o costume no pet), ou a operadora,\npelo app ou boleto dela (o costume na saúde humana) — aí a clínica recebe o valor cheio da operadora.\nEspelhado no app com os mesmos números.\n\nValores: `0` = Clinica; `1` = Operadora.",
        "format": "int32"
      },
      "EnumDescontoFator": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "Valores: `0` = Fixo; `1` = Porcentagem.",
        "format": "int32"
      },
      "EnumDocumentoTipo": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6
        ],
        "type": "integer",
        "description": "Valores: `0` = Receita; `1` = Guia; `2` = Termo; `3` = Exame; `4` = Anexo; `5` = Contrato; `6` = Atestado.",
        "format": "int32"
      },
      "EnumEncaminhamentoSituacao": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "description": "O que a página do QR mostra: o status gravado combinado com a venda firme e a validade. Não vai para o banco.\n\nValores: `0` = AguardandoAprovacao; `1` = ProntoParaRetirar; `2` = Utilizado; `3` = Vencido; `4` = Cancelado.",
        "format": "int32"
      },
      "EnumFormaPagamento": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7
        ],
        "type": "integer",
        "description": "Valores: `0` = Debito; `1` = Credito; `2` = Boleto; `3` = Dinheiro; `4` = Pix; `5` = Permuta; `6` = Reembolso; `7` = Convenio.",
        "format": "int32"
      },
      "EnumLeadAgrupamento": {
        "enum": [
          "Nenhum",
          "Nome",
          "Email",
          "Telefone"
        ],
        "type": "string",
        "description": "Junta na lista os leads repetidos, em texto. `Nenhum` = não agrupar (padrão); `Nome` = mesmo nome; `Email` = mesmo e-mail; `Telefone` = mesmo telefone."
      },
      "EnumLeadMotivoDescarte": {
        "enum": [
          "SemRetorno",
          "JaTemSistema",
          "SemVerba",
          "NaoEhVeterinario",
          "ContatoInvalido",
          "EncerrouAtividade",
          "JaEhCliente",
          "Obito",
          "Outro"
        ],
        "type": "string",
        "description": "Por que o contato saiu do funil, em texto. Só vem quando a etapa é Descartado. `SemRetorno` = Sem retorno; `JaTemSistema` = Já tem sistema; `SemVerba` = Sem verba; `NaoEhVeterinario` = Não é veterinário; `ContatoInvalido` = Contato inválido; `EncerrouAtividade` = Encerrou atividade; `JaEhCliente` = Já é cliente; `Obito` = Óbito do pet; `Outro` = Outro."
      },
      "EnumLeadSegmento": {
        "enum": [
          "AClassificar",
          "Volante",
          "Clinica",
          "Petshop",
          "Rede",
          "NaoElegivel"
        ],
        "type": "string",
        "description": "Segmento comercial do contato, em texto. `AClassificar` = A classificar; `Volante` = Volante; `Clinica` = Clínica; `Petshop` = Petshop; `Rede` = Rede; `NaoElegivel` = Não elegível."
      },
      "EnumLeadStatus": {
        "enum": [
          "Novo",
          "EmContato",
          "Convertido",
          "Descartado",
          "Qualificado",
          "Proposta"
        ],
        "type": "string",
        "description": "Etapa do funil, em texto. Na ordem do funil: Novo, EmContato, Qualificado, Proposta e Convertido; Descartado é quem saiu do funil. `Novo` = Novo; `EmContato` = Em contato; `Convertido` = Convertido; `Descartado` = Descartado; `Qualificado` = Qualificado; `Proposta` = Proposta."
      },
      "EnumLeadTipo": {
        "enum": [
          "AnuncioServico",
          "AnuncioIndustria",
          "InteresseVeterinario",
          "ContatoTutor",
          "CuradoriaCurriculo",
          "SolicitacaoIaPremium",
          "RiscoChurn",
          "SolicitacaoContaDigital",
          "RetornoDeSaude",
          "Outro"
        ],
        "type": "string",
        "description": "Tipo do contato, em texto. `AnuncioServico` = Anúncio (serviço); `AnuncioIndustria` = Anúncio (indústria); `InteresseVeterinario` = Veterinário interessado; `ContatoTutor` = Responsável legal; `CuradoriaCurriculo` = Curadoria de currículo; `SolicitacaoIaPremium` = IA Premium; `RiscoChurn` = Risco de churn; `SolicitacaoContaDigital` = Pedido de conta digital; `RetornoDeSaude` = Retorno de saúde; `Outro` = Outro."
      },
      "EnumModoRetirada": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "Como o parceiro confirma que o responsável legal usou o que a clínica já cobrou.\n\nValores: `0` = Nenhum; `1` = BaixaNoHub; `2` = Redirecionamento; `3` = QrDoPrograma.",
        "format": "int32"
      },
      "EnumMotivoDemissao": {
        "enum": [
          1,
          2,
          99
        ],
        "type": "integer",
        "description": "Por que a clínica demitiu o responsável legal; categoria fixa para a clínica poder contar e filtrar depois.\n\nValores: `1` = DebitoNaoPago; `2` = DiscursoDeOdio; `99` = Outro.",
        "format": "int32"
      },
      "EnumNotaStatus": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5
        ],
        "type": "integer",
        "description": "status da nota de serviço\n\nValores: `0` = Aprovando; `1` = Contratada; `2` = Processando; `3` = Processada; `4` = Cancelada; `5` = Estornada.",
        "format": "int32"
      },
      "EnumOrigemPeso": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Origem de um ponto de peso na linha do tempo unificada do paciente.\n\nValores: `0` = Pesagem; `1` = Ficha; `2` = Internacao.",
        "format": "int32"
      },
      "EnumOrigemRegistro": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Quais registros listar: os da plataforma e os da clínica (padrão), só os da clínica ou só os da plataforma.\n\nValores: `0` = Todos; `1` = Personalizado; `2` = Sistema.",
        "format": "int32"
      },
      "EnumParentesco": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6
        ],
        "type": "integer",
        "description": "Grau de parentesco de um antecedente familiar. Atendevet.Domain.Model.Enums.EnumParentesco.Linhagem cobre ninhada/plantel\n(veterinária), onde o parente exato raramente é conhecido.\n\nValores: `0` = Mae; `1` = Pai; `2` = Irmao; `3` = Avo; `4` = Filho; `5` = Linhagem; `6` = Outro.",
        "format": "int32"
      },
      "EnumPesquisaTipo": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8
        ],
        "type": "integer",
        "description": "Valores: `0` = NA; `1` = Facebook; `2` = Instagram; `3` = Google; `4` = Site; `5` = IndicacaoAmigos; `6` = IndicacaoVeterinarios; `7` = Plataforma; `8` = Outros.",
        "format": "int32"
      },
      "EnumPlanoTipo": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "description": "Valores: `0` = Start; `1` = Profissional; `2` = SemEstresse; `3` = MinhasRegras; `4` = Gratuito.",
        "format": "int32"
      },
      "EnumPorte": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "Valores: `0` = Indefinido; `1` = Pequeno; `2` = Medio; `3` = Grande.",
        "format": "int32"
      },
      "EnumServicoTipo": {
        "enum": [
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "Distingue itens do catálogo entre serviço prestado (mão de obra), produto físico cobrado\nitem a item e insumo de uso interno. Mantemos a entidade `Servico`\ncomo nome interno por retrocompatibilidade — este enum é a forma de classificar\no que está sendo cobrado do cliente final.\n\nValores: `1` = Servico; `2` = Produto; `3` = Insumo.",
        "format": "int32"
      },
      "EnumSexoTipo": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Valores: `0` = Indefinido; `1` = Macho; `2` = Femea.",
        "format": "int32"
      },
      "EnumSituacaoCobranca": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "Em que pé está a cobrança da conta, para o comercial agir. O app espelha os números em `SituacaoDeCobrancaDto`.\n\nValores: `0` = Inadimplente; `1` = ARenovar; `2` = RenovacaoVencida; `3` = AVencer.",
        "format": "int32"
      },
      "EnumTaxaBase": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "Sobre que valor a taxa em % incide. Padrão de mercado: o que o cliente realmente pagou\n(item já com o seu desconto e a parte rateada do desconto geral da nota).\n\nValores: `0` = AposDescontos; `1` = AntesDosDescontos.",
        "format": "int32"
      },
      "EnumTaxaDestino": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "description": "destino padrão do repasse de uma taxa do catálogo\n\nValores: `0` = Executante; `1` = Clinica; `2` = EscolherNaVenda; `3` = Membro.",
        "format": "int32"
      },
      "EnumTaxaFator": {
        "enum": [
          0,
          1
        ],
        "type": "integer",
        "description": "tipo do work flow da taxa\n\nValores: `0` = Fixo; `1` = Dinamica.",
        "format": "int32"
      },
      "EnumTemperamento": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7
        ],
        "type": "integer",
        "description": "Valores: `0` = Indefinido; `1` = Agitado; `2` = Apatico; `3` = Confuso; `4` = Irascivel; `5` = Nervoso; `6` = CarinhosoD; `7` = CarinhosoF.",
        "format": "int32"
      },
      "EnumTipoSanguineo": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5,
          6,
          7,
          8
        ],
        "type": "integer",
        "description": "Valores: `0` = Indefinido; `1` = Ap; `2` = An; `3` = Bp; `4` = Bn; `5` = ABp; `6` = ABn; `7` = Op; `8` = On.",
        "format": "int32"
      },
      "EnumUsuarioPerfil": {
        "enum": [
          0,
          1,
          2,
          777
        ],
        "type": "integer",
        "description": "perfil de usuário na plataforma\n\nValores: `0` = Colaborador; `1` = Proprietario; `2` = Parceiro; `777` = Administrador.",
        "format": "int32"
      },
      "EnumUsuarioStatus": {
        "enum": [
          0,
          1,
          2,
          3,
          4,
          5
        ],
        "type": "integer",
        "description": "Valores: `0` = Testando; `1` = Pendente; `2` = Ativo; `3` = Liberado; `4` = Inadimplente; `5` = Cancelado.",
        "format": "int32"
      },
      "EnumVerticalCatalogo": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "description": "Em que vertical o item do catálogo faz sentido: veterinária, saúde humana ou as duas.\n\nValores: `0` = Ambas; `1` = Veterinaria; `2` = Humana.",
        "format": "int32"
      },
      "EnvioDeWebhook": {
        "required": [
          "id",
          "evento",
          "criadoEm",
          "teste",
          "versao",
          "dados"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Número do envio, o mesmo do cabeçalho `X-Atendevet-Delivery`. É o mesmo quando o envio é tentado de novo.",
            "format": "uuid"
          },
          "evento": {
            "enum": [
              "orcamento.aprovado",
              "pagamento.recebido",
              "cobranca.gerada",
              "cobranca.vencida",
              "repasse.calculado",
              "tutor.criado",
              "tutor.atualizado",
              "paciente.criado",
              "atendimento.concluido",
              "retorno.registrado",
              "vacina.aplicada",
              "vacina.vencendo",
              "aniversario.pet",
              "lead.criado",
              "lead.campanha.boas-vindas",
              "lead.campanha.triagem",
              "lead.campanha.tratamento",
              "calendario.criado",
              "agendamento.criado",
              "agendamento.remarcado",
              "agendamento.cancelado",
              "agendamento.solicitado",
              "coleta.solicitada",
              "coleta.atendida",
              "exame.anexado",
              "encaminhamento.emitido",
              "encaminhamento.lido",
              "encaminhamento.utilizado",
              "encaminhamento.cancelado",
              "documento.emitido",
              "documento.assinado",
              "internacao.iniciada",
              "alta.registrada",
              "pesagem.registrada",
              "perfil.configurado",
              "estoque.baixo",
              "estoque.entrada",
              "ficha.finalizada",
              "teleconsulta.retornada",
              "transcricao.concluida"
            ],
            "type": "string",
            "description": "O evento que aconteceu."
          },
          "criadoEm": {
            "type": "string",
            "description": "Quando o envio foi montado, em UTC.",
            "format": "date-time"
          },
          "teste": {
            "type": "boolean",
            "description": "`true` no envio de teste da tela da clínica, com dados fictícios."
          },
          "versao": {
            "type": "integer",
            "description": "Versão do formato do envio.",
            "format": "int32",
            "example": 1
          },
          "dados": {
            "type": "object",
            "description": "Os dados do evento."
          }
        },
        "description": "O corpo de todo aviso de webhook. O que vem em `dados` depende do evento (veja a tabela de eventos na introdução)."
      },
      "ErroIntegracaoTurno": {
        "type": "object",
        "properties": {
          "externoId": {
            "type": "string",
            "nullable": true
          },
          "mensagem": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "HistoricoPesoResponse": {
        "type": "object",
        "properties": {
          "pontos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PesoPontoResponse"
            },
            "description": "Pontos da série, ordenados por data (mais antigo → mais recente), deduplicados por dia.",
            "nullable": true
          },
          "atual": {
            "$ref": "#/components/schemas/PesoPontoResponse"
          },
          "unidade": {
            "type": "string",
            "description": "Unidade da série (sempre kg).",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Linha do tempo de peso do paciente, mesclando as 3 origens (Pesagem, ficha de atendimento e internação)\nnuma única série em kg. Leitura unificada — não persiste nada."
      },
      "IntegracaoTurnosResponse": {
        "type": "object",
        "properties": {
          "criados": {
            "type": "integer",
            "format": "int32"
          },
          "atualizados": {
            "type": "integer",
            "format": "int32"
          },
          "removidos": {
            "type": "integer",
            "format": "int32"
          },
          "erros": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ErroIntegracaoTurno"
            },
            "description": "Itens recusados; os demais da mesma chamada foram gravados.",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "LeadCanaisResponse": {
        "type": "object",
        "properties": {
          "origens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadContagemDoCanal"
            },
            "description": "Uma linha por `Lead.Origem` distinta, da maior para a menor. O app agrupa pelo vocabulário dele.",
            "nullable": true
          },
          "segmentos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadContagemDoSegmento"
            },
            "nullable": true
          },
          "campanhas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadContagemDaCampanha"
            },
            "description": "Os leads que chegaram por link rastreável (`utm_campaign`), da maior campanha para a menor.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "De onde vêm os leads: contagem por origem e por segmento, no mesmo universo do funil (janela de datas e dono),\nsem o filtro de canal — a leitura é justamente comparar os canais."
      },
      "LeadContagemDaCampanha": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "emAndamento": {
            "type": "integer",
            "description": "Em contato, qualificados e propostas: o que ainda está no pipeline depois da chegada.",
            "format": "int32"
          },
          "convertidos": {
            "type": "integer",
            "format": "int32"
          },
          "descartados": {
            "type": "integer",
            "format": "int32"
          },
          "campanha": {
            "type": "string",
            "nullable": true
          },
          "ondeFoiDivulgada": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Onde o link da campanha foi divulgado (`utm_source`), do que mais trouxe para o que menos trouxe.",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "LeadContagemDoCanal": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "emAndamento": {
            "type": "integer",
            "description": "Em contato, qualificados e propostas: o que ainda está no pipeline depois da chegada.",
            "format": "int32"
          },
          "convertidos": {
            "type": "integer",
            "format": "int32"
          },
          "descartados": {
            "type": "integer",
            "format": "int32"
          },
          "origem": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "LeadContagemDoSegmento": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "emAndamento": {
            "type": "integer",
            "description": "Em contato, qualificados e propostas: o que ainda está no pipeline depois da chegada.",
            "format": "int32"
          },
          "convertidos": {
            "type": "integer",
            "format": "int32"
          },
          "descartados": {
            "type": "integer",
            "format": "int32"
          },
          "segmento": {
            "$ref": "#/components/schemas/EnumLeadSegmento"
          }
        },
        "additionalProperties": false
      },
      "LeadFunilResponse": {
        "type": "object",
        "properties": {
          "novos": {
            "type": "integer",
            "format": "int32"
          },
          "emContato": {
            "type": "integer",
            "format": "int32"
          },
          "qualificados": {
            "type": "integer",
            "format": "int32"
          },
          "propostas": {
            "type": "integer",
            "format": "int32"
          },
          "convertidos": {
            "type": "integer",
            "format": "int32"
          },
          "descartados": {
            "type": "integer",
            "format": "int32"
          },
          "atrasados": {
            "type": "integer",
            "description": "Leads com a próxima ação vencida. É um corte da fila, não um estágio: não soma no total.",
            "format": "int32"
          },
          "paraHoje": {
            "type": "integer",
            "description": "Toques combinados para hoje (inclui os atrasados: é a fila que precisa sair hoje).",
            "format": "int32"
          },
          "total": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Quantidade de leads por estágio do funil e os cortes da fila de hoje."
      },
      "LeadResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "empresa": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "telefone": {
            "type": "string",
            "nullable": true
          },
          "mensagem": {
            "type": "string",
            "nullable": true
          },
          "origem": {
            "type": "string",
            "nullable": true
          },
          "tipo": {
            "$ref": "#/components/schemas/EnumLeadTipo"
          },
          "tipoDescricao": {
            "type": "string",
            "description": "Rótulo do tipo, pronto para exibir.",
            "nullable": true,
            "readOnly": true
          },
          "status": {
            "$ref": "#/components/schemas/EnumLeadStatus"
          },
          "statusDescricao": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          },
          "observacoes": {
            "type": "string",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "atualizadoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "ativo": {
            "type": "boolean"
          },
          "responsavelUsuarioId": {
            "type": "integer",
            "description": "Id do usuário dono do lead; nulo = ainda na fila comum.",
            "format": "int64",
            "nullable": true
          },
          "responsavelNome": {
            "type": "string",
            "description": "Nome do dono do lead; nulo quando o lead não tem dono ou a conta dele não existe mais.",
            "nullable": true
          },
          "atribuidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "proximaAcaoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "proximaAcao": {
            "type": "string",
            "nullable": true
          },
          "proximaAcaoAtrasada": {
            "type": "boolean",
            "description": "true quando a próxima ação combinada já venceu (comparada em UTC).",
            "readOnly": true
          },
          "segmento": {
            "$ref": "#/components/schemas/EnumLeadSegmento"
          },
          "segmentoDescricao": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          },
          "motivoDescarte": {
            "$ref": "#/components/schemas/EnumLeadMotivoDescarte"
          },
          "motivoDescarteDescricao": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          },
          "usuarioCadastradoId": {
            "type": "integer",
            "description": "Só no CRM da Atendevet: id da conta da plataforma com o mesmo e-mail. Na clínica (e pela chave de API), vem nulo.",
            "format": "int64",
            "nullable": true
          },
          "jaEhUsuario": {
            "type": "boolean",
            "description": "Já existe conta na plataforma com este e-mail (não quer dizer que o lead converteu).",
            "readOnly": true
          },
          "clienteId": {
            "type": "integer",
            "description": "Id do cliente da clínica com o mesmo e-mail, CPF ou telefone do lead; nulo se não houver.",
            "format": "int64",
            "nullable": true
          },
          "jaEhCliente": {
            "type": "boolean",
            "readOnly": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "questionarioRespondidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "temperatura": {
            "type": "integer",
            "description": "0 a 100, a mesma do diagnóstico.",
            "format": "int32"
          },
          "temperaturaFaixa": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          },
          "utmSource": {
            "type": "string",
            "description": "Link rastreável por onde chegou (`utm_*`). Nulos = chegou sem link rastreável.",
            "nullable": true
          },
          "utmMedium": {
            "type": "string",
            "nullable": true
          },
          "utmCampaign": {
            "type": "string",
            "nullable": true
          },
          "campanhaBoasVindasEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "campanhaTriagemEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "campanhaTratamentoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "ipAddress": {
            "type": "string",
            "nullable": true
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "uf": {
            "type": "string",
            "nullable": true
          },
          "cidade": {
            "type": "string",
            "nullable": true
          },
          "bairro": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Lead do CRM da clínica."
      },
      "LeadResponsePaginado": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadResponse"
            },
            "description": "Lista de itens da página atual",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de itens (sem paginação)",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "description": "Página atual (1-based)",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Quantidade de itens por página",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total de páginas disponíveis",
            "format": "int32",
            "readOnly": true
          },
          "hasNextPage": {
            "type": "boolean",
            "description": "Indica se há próxima página",
            "readOnly": true
          },
          "hasPreviousPage": {
            "type": "boolean",
            "description": "Indica se há página anterior",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Resposta paginada genérica para listagens"
      },
      "NotaPagamentoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "formaPagamento": {
            "$ref": "#/components/schemas/EnumFormaPagamento"
          },
          "notaId": {
            "type": "integer",
            "format": "int64"
          },
          "nota": {
            "$ref": "#/components/schemas/NotaResponse"
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "uri": {
            "type": "string",
            "nullable": true
          },
          "vencimento": {
            "type": "string",
            "description": "Só no recebível do convênio: quando a operadora deve pagar, quando pagou e quanto recusou.",
            "format": "date-time",
            "nullable": true
          },
          "recebidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "valorGlosado": {
            "type": "number",
            "format": "double"
          },
          "convenioLoteId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "NotaResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "numero": {
            "type": "string",
            "nullable": true
          },
          "desconto": {
            "type": "number",
            "format": "double"
          },
          "lucro": {
            "type": "number",
            "format": "double"
          },
          "total": {
            "type": "number",
            "format": "double"
          },
          "custo": {
            "type": "number",
            "format": "double"
          },
          "taxa": {
            "type": "number",
            "format": "double"
          },
          "imposto": {
            "type": "number",
            "format": "double"
          },
          "status": {
            "$ref": "#/components/schemas/EnumNotaStatus"
          },
          "emissorId": {
            "type": "integer",
            "format": "int64"
          },
          "emissor": {
            "type": "string",
            "nullable": true
          },
          "calendarioEventoId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "localId": {
            "type": "integer",
            "description": "O local que conta para relatórios e fiscal: o do compromisso, quando ele tem; senão o da própria venda.",
            "format": "int64",
            "nullable": true
          },
          "localDoCompromisso": {
            "type": "boolean",
            "description": "O local veio do compromisso da agenda: troca-se lá, não na venda."
          },
          "pacienteId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "paciente": {
            "type": "string",
            "nullable": true
          },
          "clienteId": {
            "type": "integer",
            "format": "int64"
          },
          "cliente": {
            "type": "string",
            "nullable": true
          },
          "clienteCpf": {
            "type": "string",
            "nullable": true
          },
          "clienteEndereco": {
            "type": "string",
            "nullable": true
          },
          "comentario": {
            "type": "string",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "atualizadoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "pagamentos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaPagamentoResponse"
            },
            "nullable": true
          },
          "pacienteConvenioId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "convenio": {
            "$ref": "#/components/schemas/ConvenioDaNotaResponse"
          },
          "codigoElegibilidade": {
            "type": "string",
            "nullable": true
          },
          "parteDoPlano": {
            "type": "number",
            "description": "O que a operadora paga, pelas linhas carregadas; o resto do total é do responsável legal.",
            "format": "double"
          },
          "parteDoResponsavel": {
            "type": "number",
            "format": "double"
          },
          "recebivelConvenio": {
            "$ref": "#/components/schemas/RecebivelConvenioResponse"
          }
        },
        "additionalProperties": false
      },
      "NotaResponseColunaDoKanban": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Status da coluna, pelo nome (ex.: Aprovando).",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de itens do status, sem paginação.",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Itens por coluna nesta resposta.",
            "format": "int32"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaResponse"
            },
            "description": "Primeira página de itens desta coluna.",
            "nullable": true
          },
          "hasMore": {
            "type": "boolean",
            "description": "Indica se ainda há itens além dos já carregados (habilita \"carregar mais\").",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Uma coluna: o status, o total real e a primeira página de itens."
      },
      "NotaResponseKanban": {
        "type": "object",
        "properties": {
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaResponseColunaDoKanban"
            },
            "description": "Uma coluna por status, na ordem do ciclo.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Itens agrupados por status: uma coluna por status, com a primeira página de cada uma e o total real."
      },
      "NotaResponsePaginado": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaResponse"
            },
            "description": "Lista de itens da página atual",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de itens (sem paginação)",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "description": "Página atual (1-based)",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Quantidade de itens por página",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total de páginas disponíveis",
            "format": "int32",
            "readOnly": true
          },
          "hasNextPage": {
            "type": "boolean",
            "description": "Indica se há próxima página",
            "readOnly": true
          },
          "hasPreviousPage": {
            "type": "boolean",
            "description": "Indica se há página anterior",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Resposta paginada genérica para listagens"
      },
      "NotaServicoPacienteResponse": {
        "type": "object",
        "properties": {
          "pacienteId": {
            "type": "integer",
            "format": "int64"
          },
          "notaServicoId": {
            "type": "integer",
            "format": "int64"
          },
          "paciente": {
            "type": "string",
            "nullable": true
          },
          "pacienteDetalhe": {
            "$ref": "#/components/schemas/PacienteDetalheResponse"
          }
        },
        "additionalProperties": false
      },
      "NotaServicoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "emissor": {
            "$ref": "#/components/schemas/UsuarioResponse"
          },
          "medicos": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "pagamentos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NotaPagamentoResponse"
            },
            "nullable": true
          },
          "cliente": {
            "type": "string",
            "nullable": true
          },
          "endereco": {
            "type": "string",
            "nullable": true
          },
          "desconto": {
            "type": "number",
            "format": "double"
          },
          "catalogo": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogoNotaResponse"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "Notification": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string",
            "nullable": true
          },
          "date": {
            "type": "string",
            "nullable": true,
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Mensagem de validação: key = campo, message = motivo."
      },
      "OrganizacaoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Identificador da Organização",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "description": "Nome da Organização",
            "nullable": true
          },
          "ativo": {
            "type": "boolean",
            "description": "Verifica se a Organização está ou não ativa"
          },
          "usuarioId": {
            "type": "integer",
            "description": "Indentificador do Usuario",
            "format": "int64"
          },
          "margemImposto": {
            "type": "number",
            "description": "Margem de Imposto cobrado pelo serviço da organização",
            "format": "double"
          },
          "catalogo": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CatalogoResponse"
            },
            "nullable": true
          },
          "quantidadeMembros": {
            "type": "integer",
            "description": "Membros vinculados — preenchido quando a consulta inclui `OrganizacaoUsuarios`.",
            "format": "int32"
          },
          "quantidadeItens": {
            "type": "integer",
            "description": "Itens ativos do catálogo da equipe — preenchido quando a consulta inclui `Catalogo`.",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "PacienteDetalheResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "aniversario": {
            "type": "string",
            "format": "date-time"
          },
          "idade": {
            "type": "string",
            "nullable": true
          },
          "sexo": {
            "$ref": "#/components/schemas/EnumSexoTipo"
          },
          "sangue": {
            "$ref": "#/components/schemas/EnumTipoSanguineo"
          },
          "porte": {
            "$ref": "#/components/schemas/EnumPorte"
          },
          "temperamento": {
            "$ref": "#/components/schemas/EnumTemperamento"
          },
          "castrado": {
            "type": "boolean"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "cor": {
            "type": "string",
            "nullable": true
          },
          "raca": {
            "type": "string",
            "nullable": true
          },
          "especie": {
            "type": "string",
            "nullable": true
          },
          "pelagem": {
            "type": "string",
            "nullable": true
          },
          "cliente": {
            "type": "string",
            "nullable": true
          },
          "clienteCpf": {
            "type": "string",
            "nullable": true
          },
          "clienteCnpj": {
            "type": "string",
            "nullable": true
          },
          "clienteEmail": {
            "type": "string",
            "nullable": true
          },
          "clienteTelefone": {
            "type": "string",
            "nullable": true
          },
          "medico": {
            "type": "string",
            "nullable": true
          },
          "obito": {
            "type": "boolean"
          },
          "observacaoObito": {
            "type": "string",
            "nullable": true
          },
          "obitoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "obitoPor": {
            "type": "string",
            "nullable": true
          },
          "medicoTelefone": {
            "type": "string",
            "nullable": true
          },
          "medicoCpf": {
            "type": "string",
            "nullable": true
          },
          "medicoEndereco": {
            "type": "string",
            "nullable": true
          },
          "medicoCrmV": {
            "type": "string",
            "nullable": true
          },
          "tag": {
            "type": "string",
            "nullable": true
          },
          "medicoLogo": {
            "type": "string",
            "nullable": true
          },
          "medicoLogoRodape": {
            "type": "string",
            "nullable": true
          },
          "uriFoto": {
            "type": "string",
            "nullable": true
          },
          "medicoCorporacao": {
            "type": "string",
            "nullable": true
          },
          "medicoSlogan": {
            "type": "string",
            "nullable": true
          },
          "medicoCorTema": {
            "type": "string",
            "nullable": true
          },
          "atualizadoEm": {
            "type": "string",
            "nullable": true
          },
          "pesagem": {
            "type": "string",
            "nullable": true
          },
          "corId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "racaId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "especieId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "clienteId": {
            "type": "integer",
            "format": "int64"
          },
          "prontuarioId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "numeroChip": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "ativo": {
            "type": "boolean"
          },
          "endereco": {
            "type": "string",
            "nullable": true
          },
          "carteira": {
            "$ref": "#/components/schemas/CarteiraResponse"
          }
        },
        "additionalProperties": false
      },
      "PacienteHistoricoResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Numero de identificação do historico",
            "format": "int64"
          },
          "informativo": {
            "type": "string",
            "description": "Texto informativo para organização do historico",
            "nullable": true
          },
          "json": {
            "type": "string",
            "description": "Json do Historico",
            "nullable": true
          },
          "tipo": {
            "type": "string",
            "description": "Tipo de Historico",
            "nullable": true
          },
          "usuario": {
            "type": "string",
            "description": "Usuario que criou o historico",
            "nullable": true
          },
          "ipRemoto": {
            "type": "string",
            "description": "Ip remoto do historico",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "description": "Horario de criação do historico",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "PacienteResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Numero de Identificação do paciente",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "description": "Nome do paciente",
            "nullable": true
          },
          "uriFoto": {
            "type": "string",
            "nullable": true
          },
          "tag": {
            "type": "string",
            "nullable": true
          },
          "aniversario": {
            "type": "string",
            "description": "Data de aniversario do paciente",
            "format": "date-time"
          },
          "castrado": {
            "type": "boolean",
            "description": "Verifica se o paciente é ou não Castrado"
          },
          "sexo": {
            "$ref": "#/components/schemas/EnumSexoTipo"
          },
          "sangue": {
            "$ref": "#/components/schemas/EnumTipoSanguineo"
          },
          "porte": {
            "$ref": "#/components/schemas/EnumPorte"
          },
          "temperamento": {
            "$ref": "#/components/schemas/EnumTemperamento"
          },
          "cor": {
            "type": "string",
            "description": "Cor do paciente",
            "nullable": true
          },
          "raca": {
            "type": "string",
            "description": "Raça do paciente",
            "nullable": true
          },
          "clienteEmail": {
            "type": "string",
            "nullable": true
          },
          "especie": {
            "type": "string",
            "nullable": true
          },
          "telefone": {
            "type": "string",
            "description": "Celular ou telefone do responsável legal",
            "nullable": true
          },
          "cliente": {
            "type": "string",
            "description": "Nome do responsável legal (cliente) do paciente",
            "nullable": true
          },
          "clienteId": {
            "type": "integer",
            "description": "Id do responsável legal (cliente) do paciente",
            "format": "int64"
          },
          "prontuarioId": {
            "type": "integer",
            "description": "Id do Prontuario do paciente",
            "format": "int64",
            "nullable": true
          },
          "ativo": {
            "type": "boolean",
            "description": "Verifica se o paciente é ou não ativo"
          },
          "numeroChip": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "description": "Horario de criação do cadastro do paciente",
            "format": "date-time"
          },
          "obito": {
            "type": "boolean"
          },
          "observacaoObito": {
            "type": "string",
            "nullable": true
          },
          "obitoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "obitoPor": {
            "type": "string",
            "nullable": true
          },
          "avisoObito": {
            "type": "string",
            "description": "Aviso sobre o óbito, quando houver (ex.: óbito revertido de paciente com internação encerrada). Não é gravado.",
            "nullable": true
          },
          "ultimaPesagem": {
            "$ref": "#/components/schemas/PesagemResponse"
          }
        },
        "additionalProperties": false
      },
      "ParceiroUnidadeResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "parceiroId": {
            "type": "integer",
            "format": "int64"
          },
          "codigo": {
            "type": "string",
            "nullable": true
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "cep": {
            "type": "string",
            "nullable": true
          },
          "logradouro": {
            "type": "string",
            "nullable": true
          },
          "numero": {
            "type": "string",
            "nullable": true
          },
          "bairro": {
            "type": "string",
            "nullable": true
          },
          "cidade": {
            "type": "string",
            "nullable": true
          },
          "uf": {
            "type": "string",
            "nullable": true
          },
          "endereco": {
            "type": "string",
            "description": "\"Rua X, 100 - Centro - Campinas/SP - CEP 13010-000\".",
            "nullable": true
          },
          "whatsApp": {
            "type": "string",
            "nullable": true
          },
          "horario": {
            "type": "string",
            "nullable": true
          },
          "observacao": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Unidade da filial onde o responsável legal é atendido. Sem dado de cliente: é vitrine."
      },
      "PesagemResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Id da pesagem",
            "format": "int64"
          },
          "peso": {
            "type": "string",
            "description": "Peso do paciente",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "description": "Horario de criação da pesagem",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "PesoPontoResponse": {
        "type": "object",
        "properties": {
          "dataHora": {
            "type": "string",
            "description": "Momento do registro (data da pesagem/ficha ou aferição de internação).",
            "format": "date-time"
          },
          "pesoKg": {
            "type": "number",
            "description": "Peso em quilos (normalizado a partir de qualquer origem).",
            "format": "double"
          },
          "origem": {
            "$ref": "#/components/schemas/EnumOrigemPeso"
          },
          "responsavel": {
            "type": "string",
            "description": "Responsável pelo registro, quando disponível.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Um ponto de peso (kg) na linha do tempo unificada do paciente."
      },
      "RecebivelConvenioResponse": {
        "type": "object",
        "properties": {
          "pagamentoId": {
            "type": "integer",
            "format": "int64"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "vencimento": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "recebidoEm": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "valorGlosado": {
            "type": "number",
            "format": "double"
          },
          "loteId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "loteStatus": {
            "$ref": "#/components/schemas/EnumConvenioLoteStatus"
          }
        },
        "additionalProperties": false,
        "description": "A parte do plano a receber da operadora: o pagamento Atendevet.Domain.Model.Enums.EnumFormaPagamento.Convenio da venda."
      },
      "ReceitaModeloResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Id da receita",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "description": "Nome da receita",
            "nullable": true
          },
          "observacao": {
            "type": "string",
            "nullable": true
          },
          "html": {
            "type": "string",
            "description": "Html da receita",
            "nullable": true
          },
          "ativo": {
            "type": "boolean"
          },
          "usuarioId": {
            "type": "integer",
            "description": "Id do usuario que gerou a receita",
            "format": "int64"
          },
          "usuario": {
            "type": "string",
            "description": "Nome do usuario que gerou a receita",
            "nullable": true
          },
          "tipo": {
            "$ref": "#/components/schemas/EnumDocumentoTipo"
          },
          "crmv": {
            "type": "string",
            "description": "CRMV do usuario que gerou a receita",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "contagemUso": {
            "type": "integer",
            "description": "Contador de quantas vezes o modelo foi utilizado",
            "format": "int32"
          },
          "tipoId": {
            "type": "integer",
            "format": "int64"
          },
          "publico": {
            "type": "boolean",
            "description": "true = modelo da plataforma, comum a todas as clínicas e somente leitura; false = modelo da clínica."
          }
        },
        "additionalProperties": false
      },
      "ReceitaModeloResponsePaginado": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReceitaModeloResponse"
            },
            "description": "Lista de itens da página atual",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de itens (sem paginação)",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "description": "Página atual (1-based)",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Quantidade de itens por página",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total de páginas disponíveis",
            "format": "int32",
            "readOnly": true
          },
          "hasNextPage": {
            "type": "boolean",
            "description": "Indica se há próxima página",
            "readOnly": true
          },
          "hasPreviousPage": {
            "type": "boolean",
            "description": "Indica se há página anterior",
            "readOnly": true
          }
        },
        "additionalProperties": false,
        "description": "Resposta paginada genérica para listagens"
      },
      "ReceitaTemplateRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "description": "Nome da receita",
            "nullable": true
          },
          "html": {
            "type": "string",
            "description": "Html da receita",
            "nullable": true
          },
          "observacao": {
            "type": "string",
            "nullable": true
          },
          "tipo": {
            "$ref": "#/components/schemas/EnumDocumentoTipo"
          }
        },
        "additionalProperties": false
      },
      "ServicoTaxaResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "nome": {
            "type": "string",
            "nullable": true
          },
          "ativo": {
            "type": "boolean"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "visivel": {
            "type": "boolean"
          },
          "fator": {
            "$ref": "#/components/schemas/EnumTaxaFator"
          },
          "base": {
            "$ref": "#/components/schemas/EnumTaxaBase"
          },
          "taxaCatalogoId": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "destinoPadrao": {
            "$ref": "#/components/schemas/EnumTaxaDestino"
          },
          "beneficiarioPadraoId": {
            "type": "integer",
            "description": "membro fixo do repasse (destino Membro) — a venda pré-seleciona este beneficiário",
            "format": "int64",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "TurnoIntegracaoItem": {
        "type": "object",
        "properties": {
          "externoId": {
            "type": "string",
            "nullable": true
          },
          "profissionalEmail": {
            "type": "string",
            "description": "E-mail de um profissional ativo da clínica dona da chave de API.",
            "nullable": true
          },
          "localCodigo": {
            "type": "string",
            "description": "Código de um local ativo da clínica; nulo = sem local.",
            "nullable": true
          },
          "inicio": {
            "type": "string",
            "format": "date-time"
          },
          "fim": {
            "type": "string",
            "format": "date-time"
          },
          "observacao": {
            "type": "string",
            "nullable": true
          },
          "cancelado": {
            "type": "boolean",
            "description": "Verdadeiro = o plantão foi cancelado na origem e sai da escala.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Plantão vindo de sistema externo (hospital, escala). Atendevet.Domain.Arguments.Agendamento.TurnoIntegracaoItem.ExternoId diz qual plantão criar ou atualizar."
      },
      "UsuarioResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Numero de identificação do usuario",
            "format": "int64"
          },
          "codigoUsuario": {
            "type": "string",
            "nullable": true
          },
          "nome": {
            "type": "string",
            "description": "Nome do usuario",
            "nullable": true
          },
          "capaUrl": {
            "type": "string",
            "nullable": true
          },
          "logoSecundariaUrl": {
            "type": "string",
            "nullable": true
          },
          "imagemPerfilUrl": {
            "type": "string",
            "nullable": true
          },
          "cidade": {
            "type": "string",
            "nullable": true
          },
          "uf": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "description": "Email do usuario",
            "nullable": true
          },
          "corporativo": {
            "type": "string",
            "description": "Nome corporativo do usuario",
            "nullable": true
          },
          "perfil": {
            "$ref": "#/components/schemas/EnumUsuarioPerfil"
          },
          "status": {
            "$ref": "#/components/schemas/EnumUsuarioStatus"
          },
          "ativo": {
            "type": "boolean",
            "description": "Verifica se o usuario é ativo"
          },
          "crmv": {
            "type": "string",
            "description": "CRMV do usuario",
            "nullable": true
          },
          "mapa": {
            "type": "string",
            "nullable": true
          },
          "cpf": {
            "type": "string",
            "description": "CPF do Usuario",
            "nullable": true
          },
          "celular": {
            "type": "string",
            "description": "Telefone Celular do usuario",
            "nullable": true
          },
          "whatsApp": {
            "type": "string",
            "description": "Numero de WhatsApp do usuario",
            "nullable": true
          },
          "telefone": {
            "type": "string",
            "description": "Numero de telefone residencial do usuario",
            "nullable": true
          },
          "endereco": {
            "type": "string",
            "description": "Endereço do usuario",
            "nullable": true
          },
          "aniversario": {
            "type": "string",
            "description": "Aniversário do usuario",
            "format": "date-time",
            "nullable": true
          },
          "slogan": {
            "type": "string",
            "description": "Slogan do usuario",
            "nullable": true
          },
          "corTema": {
            "type": "string",
            "description": "Cor do tema do usuario",
            "nullable": true
          },
          "cnpj": {
            "type": "string",
            "description": "Informativo do cnpj ao usuario",
            "nullable": true
          },
          "inscricaoEstadual": {
            "type": "string",
            "description": "Inscrição estadual",
            "nullable": true
          },
          "informativoPagamento": {
            "type": "string",
            "description": "Informativo de pagamento do usuario",
            "nullable": true
          },
          "proprietario": {
            "type": "integer",
            "description": "Id de transferencia do usuario",
            "format": "int64",
            "nullable": true
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "equipes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrganizacaoResponse"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "VendasDoClienteResponse": {
        "type": "object",
        "properties": {
          "clienteId": {
            "type": "integer",
            "description": "Nulo na linha das vendas sem responsável legal vinculado (só vem sem o filtro de clientes).",
            "format": "int64",
            "nullable": true
          },
          "quantidade": {
            "type": "integer",
            "description": "Vendas firmes do cliente no período. Venda de dois responsáveis legais conta para os dois.",
            "format": "int32"
          },
          "valor": {
            "type": "number",
            "description": "Soma das vendas firmes do cliente, igual ao faturamento do relatório financeiro por cliente. Venda de dois\nresponsáveis legais é rateada pelo valor dos itens de cada um.",
            "format": "double"
          },
          "ultimaVendaEm": {
            "type": "string",
            "description": "Momento da venda mais recente do período, no fuso do cabeçalho X-Timezone (sem ele, Brasília).",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "VendasDoPeriodoResponse": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number",
            "description": "Soma das vendas firmes (Contratada, Processando e Processada), a mesma régua do relatório financeiro.",
            "format": "double"
          },
          "quantidade": {
            "type": "integer",
            "description": "Quantas vendas firmes há no período.",
            "format": "int32"
          },
          "pago": {
            "type": "number",
            "description": "Parte do total já registrada como pagamento da venda.",
            "format": "double"
          },
          "emAberto": {
            "type": "number",
            "description": "Parte do total que falta receber: Total − Pago.",
            "format": "double"
          },
          "porStatus": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VendasPorStatusResponse"
            },
            "description": "Uma linha por status, sempre os seis, na ordem do ciclo da venda.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Vendas do período só com números: nenhum nome, documento, endereço ou pet, nem custo, lucro, taxa ou imposto."
      },
      "VendasPorStatusResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "Aprovando (orçamento), Contratada (aprovada, sem pagamento), Processando (paga em parte), Processada (quitada),\nCancelada ou Estornada.",
            "nullable": true
          },
          "quantidade": {
            "type": "integer",
            "format": "int32"
          },
          "valor": {
            "type": "number",
            "format": "double"
          },
          "entraNoTotal": {
            "type": "boolean",
            "description": "Se o status soma no Total: só Contratada, Processando e Processada."
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "Chave de API criada nas **Configurações corporativas → Configurações → Chaves de API**. Envie a chave completa (`avk_<prefixo>_<segredo>`) no cabeçalho `X-Api-Key`. A chave alcança só os escopos marcados nela e a clínica de quem a criou.",
        "name": "X-Api-Key",
        "in": "header"
      }
    }
  },
  "security": [
    {
      "ApiKey": [ ]
    }
  ],
  "tags": [
    {
      "name": "Clientes",
      "description": "Clientes da clínica, os responsáveis legais pelos pacientes: cadastro, busca, grupos, endereços e vínculo com os pacientes."
    },
    {
      "name": "CRM — gestão",
      "description": "Leads do CRM da clínica: lista com filtros, ficha, funil por estágio, canais de origem, tags, lote, campanha e temperatura. Pela chave de API é só leitura (lista, ficha, funil e canais), até 60 chamadas por minuto somando as quatro rotas; para enviar leads, use o formulário de entrada."
    },
    {
      "name": "Documentos",
      "description": "Documentos clínicos e administrativos da clínica: modelos (receita, atestado, termo e outros), emissão com os dados do paciente, assinatura eletrônica e histórico."
    },
    {
      "name": "Encaminhamentos ao parceiro",
      "description": "Item do orçamento feito ou retirado na unidade do parceiro: a clínica cobra na nota, o responsável legal leva o QR e o parceiro dá a baixa no Hub ou pela chave de API."
    },
    {
      "name": "Integrações — plantões",
      "description": "Sistema do hospital ou de escala grava os plantões da equipe na escala da clínica, por chave de API."
    },
    {
      "name": "Notas e vendas",
      "description": "Notas da clínica: orçamentos (status Aprovando) e vendas (demais status), com itens, descontos, pagamentos e parcelas."
    },
    {
      "name": "Pacientes",
      "description": "Pacientes (pets) da clínica: ficha, fotos, histórico de ações, pesagens e peso."
    },
    {
      "name": "Pacientes — antecedentes",
      "description": "Antecedentes pessoais (condições, cirurgias, alergias, medicamentos em uso) e familiares do paciente."
    },
    {
      "name": "Relatórios",
      "description": "Relatórios gerenciais da clínica: financeiro, vacinas, atendimentos e exportações. Pela chave de API, os números de venda do período, para conferir com outro sistema."
    }
  ]
}