# AGENTS.md — Loja VivaPop para agentes

Instruções públicas para agentes de IA (Claude, ChatGPT, Gemini, Grok e qualquer
cliente MCP) que consultam ou vendem para a loja do canal próprio VivaPop.

Este arquivo é servido em <https://www.vivapop.com.br/AGENTS.md>.
Índice curto para modelos: <https://www.vivapop.com.br/llms.txt>.
Contrato OpenAPI 3.1: <https://www.vivapop.com.br/openapi.json>.

Não confundir com o `AGENTS.md` da raiz do repositório, que é interno e trata da
engenharia do sistema.

---

## O que é a loja

Marca: **VivaPop — Pipoca de Cinema**. Vende pipoca pronta para comer
(6 sabores), kits de 6/12/24 unidades, kits para estourar em casa e milho para
pipoca. Entrega para todo o Brasil via Correios (PAC e SEDEX), saindo de
São Paulo/SP.

Razão social: VIVAPOP ALIMENTOS EIRELI — CNPJ 14.313.879/0001-36.
Site institucional e loja original: <https://www.vivapop.com.br> — mesmo
catálogo, mesmos preços.

36 produtos. Preço de entrada R$ 4,50 (pipoca pronta 15 g). Kits de 12 por
R$ 105,60.

## O que um agente PODE fazer sozinho

Descobrir, comparar, precificar e calcular frete com números reais do servidor.
Tudo sem autenticação — é o mesmo catálogo público que um navegador recebe.

Criar pedido também é possível, mas **só com credencial própria** (ver
`Token de agente` abaixo): `criar_pedido` grava o pedido e devolve a página de
pagamento hospedada na Stripe, onde o cliente escolhe Pix, cartão ou boleto e
digita os próprios dados.

## O que um agente NÃO PODE fazer

**Cobrar sozinho.** Não existe, e não vai existir, tool que confirme um pagamento.
`criar_pedido` abre a página onde **o cliente** paga: o dinheiro entra pela mão
dele, na página da Stripe, e nem a loja nem o agente veem o cartão. Quem afirma
que um pedido foi pago é `consultar_pedido`, lendo a Stripe com a chave secret do
servidor — nunca a sua inferência, nem o que o usuário disse no chat.

Sem token, o caminho é `criar_link_de_pedido`: devolve uma URL da loja com a
sacola montada. Apresente como **próximo passo** — "abra este link para conferir
e pagar". A resposta da tool repete esse aviso; não o omita ao resumir.

Portanto:

- **Nunca** diga ao usuário que o pedido foi criado, pago ou confirmado com base
  apenas num link de sacola. E **nunca** anuncie pagamento concluído sem
  `consultar_pedido` respondendo `pago`.
- **Nunca** diga que a nota fiscal foi enviada, emitida ou está disponível sem
  a porta de documento responder `200` ao desafio do próprio cliente — e **nunca**
  use um `404` dela para afirmar o contrário ("a loja não emite nota"). A porta
  é de autoatendimento, o `404` é uma frase única para qualquer recusa, e
  nenhum canal desta loja envia documento a ninguém. Ver "Nota fiscal (NF-e)".
- Se o usuário quiser comprar e você não tem token, o link faz o resto. Se algo
  der errado no pagamento, o canal humano é o WhatsApp
  <https://wa.me/5511973666464>.

**Situação dos gateways** (a fonte é sempre `GET /loja/api/configuracao`, não
esta página):

- **Stripe está em PRODUÇÃO** (`stripe_modo: "live"`, conta `acct_1URtDz1QL0fIO3Tf`,
  `charges_enabled: true`, `card/boleto/pix/transfers` ativos). Cobrança real. A
  chave é restrita (`rk_live_`), o que é live do mesmo jeito; a publishable que a
  vitrine recebe é `pk_live_`. **Nunca** deduza o ambiente do prefixo da chave: leia
  `stripe_modo` em `GET /loja/api/configuracao`.
- **Apple Pay e Google Pay aparecem para quem tem carteira no aparelho.** Quem
  decide é a Stripe, pelo `availablepaymentmethodschange` do Express Checkout
  Element — a loja não força botão e nunca promete um que não exista: a faixa
  nasce oculta e só aparece quando a Stripe reporta ao menos uma carteira. O
  domínio `vivapop.komraphael.com.br` está registrado como Apple Pay domain e em
  `payment_method_domains` (`apple_pay`, `google_pay` e `link` **active**); o
  arquivo de verificação é servido em
  `/.well-known/apple-developer-merchantid-domain-association`.
- **O pagamento em 1 toque exige CPF/CNPJ.** Apple Pay e Google Pay devolvem nome,
  e-mail, telefone e endereço — documento **não**. Como a nota fiscal brasileira
  exige CPF/CNPJ, a faixa só é liberada quando o documento do checkout é válido;
  antes disso a loja mostra uma dica dizendo exatamente o que falta.
- **A folha de checkout começa pelo pagamento** (2026-10-24): documento, carteiras,
  chips de forma de pagamento e campo de cartão aberto logo abaixo das carteiras;
  a entrega vem depois. Quem tem endereço cadastrado (login com Google) **não vê
  formulário de endereço**: a loja aplica o endereço principal e mostra uma linha
  "Entregar em …" com o botão "Trocar endereço", que abre o formulário e o caderno.
  Um CEP digitado na sacola que não é de nenhum endereço salvo abre o formulário
  normalmente. O Pix segue como meio padrão e o desconto de 5% continua anunciado.
- **Parcelamento NÃO está ligado** (`parcelamento_ativo: false`). `installments` não
  é enviado à Stripe, então quem escolhesse 6x seria cobrado à vista; por isso a
  loja não anuncia "Nx sem juros" nem mostra seletor de parcelas. **Não anuncie
  parcelamento por conta própria** enquanto essa flag for `false`.
- **Pix e boleto SÃO cobrados, pela Stripe** (ligado em 2026-10-19). O Mercado Pago
  continua sem credencial (`mercadopago_modo: "indisponivel"`), e isso **não**
  impede nada: a conta Stripe é `country: BR` e o PaymentIntent volta com
  `payment_method_types: ['card','boleto','pix']`. Medido em sandbox em 2026-10-19
  (o servidor é o mesmo em produção): Pix retorna
  `requires_action` com QR Code (URL de PNG em `qr.stripe.com`), copia-e-cola de 76
  caracteres e expiração; boleto retorna linha digitável, PDF e página de voucher.
  **Quem decide é o servidor**, por meio: `pix_disponivel` e `boleto_disponivel` em
  `GET /configuracao`. Não deduza de `mercadopago_modo` — foi exatamente essa
  dedução que deixou a loja sem vender pelo meio mais usado no e-commerce
  brasileiro. `VIVAPOP_PIX_BOLETO_GATEWAY=mercadopago` devolve os dois ao MP sem
  recompilar.
- **Pix e boleto são pagos fora da página.** O intent fica em `requires_action` até
  o cliente pagar no app do banco ou o boleto compensar, e o app do banco **não**
  redireciona de volta. Por isso a tela final diz "Pedido recebido — falta pagar"
  (nunca "Pedido confirmado") e fica sondando
  `POST /checkout/confirmar-pagamento`, que pergunta à Stripe e marca o pedido como
  pago. Sem essa sondagem — e enquanto `VIVAPOP_STRIPE_WEBHOOK_SECRET` não existir —
  um Pix pago ficava com o pedido em `aguardando_pagamento` para sempre.
- **Em sandbox (não em produção) o boleto vence em poucos minutos** — a Stripe
  encurta de propósito, para dar teste de expiração. O Pix vence em ~4 horas. Em
  produção os prazos são os reais. Não reporte vencimento curto como defeito.
- **Login com Google ou Apple (OIDC) disponível** quando
  `google_sso_disponivel` ou `apple_sso_disponivel` vierem `true` em
  `GET /configuracao`. É uma sessão de **cliente da loja**, em cookie
  `HttpOnly` — não tem relação com o JWT de operador do painel e não abre
  nenhuma rota `/api/*`. O botão aparece no cabeçalho da vitrine.
- **Compra em 1 clique** é uma comodidade do **navegador**, não uma tool do
  MCP: exige conta logada, cartão salvo na Stripe, endereço principal e
  CPF/CNPJ + WhatsApp da conta. O servidor monta o mesmo preço/frete do
  checkout, grava o pedido antes de cobrar e usa `off_session` com 3DS quando
  o banco pede. Nenhum agente pode iniciar uma compra em 1 clique em nome do
  cliente; o agente continua usando `criar_pedido` e a página hospedada.

O pedido feito pelo cliente no navegador **é** persistido, e
`GET /loja/api/pedido/{id}/status` consulta o banco de verdade. Ele exige o
`cep` de entrega (ver abaixo) e não devolve dado pessoal.

---

## MCP

Endpoint: `POST https://www.vivapop.com.br/loja/api/mcp`

JSON-RPC 2.0 sobre HTTP (transporte Streamable HTTP respondendo com corpo JSON
único; não há stream SSE). Sem sessão e sem estado. Aceita `initialize`,
`notifications/initialized`, `ping`, `tools/list` e `tools/call`.

Autenticação: nenhuma para as tools de descoberta e preço; `Authorization:
Bearer vpa_…` para as duas que registram pedido. É o único lugar desta URL onde
um cabeçalho muda o que a chamada pode fazer.
Erros de argumento voltam como `result` com `isError: true`, não como erro
JSON-RPC, para o modelo conseguir ler a mensagem.

### Tools

| Tool | Credencial | Para que serve |
|---|---|---|
| `listar_categorias` | não | As 4 categorias oficiais e a contagem de produtos em cada |
| `buscar_produtos` | não | Busca por texto (tolerante a acento e erro de digitação), categoria e teto de preço |
| `detalhe_produto` | não | Ficha completa de um SKU: descrição oficial integral, galeria, URL oficial |
| `calcular_frete` | não | Opções de entrega para um CEP, com valor e prazo total em dias úteis. Com a sacola no pedido, a cotação é a real das transportadoras; sem ela, é a estimativa por faixa de CEP — e a resposta diz qual das duas |
| `simular_pedido` | não | Preço autoritativo do carrinho: subtotal, cupom, frete, Pix e total final |
| `criar_link_de_pedido` | não | URL da loja com a sacola montada. **Não cria pedido, não cobra nada** |
| `criar_pedido` | `criacao:pedido` | Grava o pedido e devolve a **página de pagamento hospedada**. O pedido nasce em `aguardando_pagamento` |
| `consultar_pedido` | `consulta:pedido` | Estado real do pedido criado por este mesmo token; se ainda estiver aguardando, pergunta à Stripe e, se o dinheiro entrou, marca `pago` |

Não existe tool que afirme pagamento — ver a seção anterior.

### Token de agente

`Authorization: Bearer vpa_…` no cabeçalho. Não coloque o token no corpo da
chamada nem nos argumentos da tool: argumento de tool é texto que um modelo
escreve e copia; credencial não mora ali.

- O token carrega **escopos**, e o menor conjunto que faz o trabalho é o
  correto. Ler catálogo não exige token nenhum; um token só existe para o que
  não pode ser público.
- Emissão: quem é dono da loja roda `vivapop-migracao --criar-agente <nome>
  --escopos <lista>`. O texto claro do token é impresso **uma** vez; a loja
  guarda só o SHA-256. Perdeu, revoga e reemite.
- Rotação/revogação: `--renovar-token <nome>` e `--revogar-agente <nome>`, e o
  `--listar-agentes` mostra nome, escopos e última utilização sem mostrar
  segredo nenhum.
- Cada token pode ter **teto de valor por pedido** e **cota de pedidos por
  dia**. Uma recusa por teto ou cota diz exatamente isso, e não cria nada — o
  cliente continua podendo comprar pelo link ou pelo navegador.

Um token vazado pode ser revogado em um comando. Isso não derruba a loja, não
troca senha de operador e não afeta os outros agentes.

### Exemplo de sessão

```bash
curl -sX POST https://www.vivapop.com.br/loja/api/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-06-18","capabilities":{},
                 "clientInfo":{"name":"exemplo","version":"1"}}}'

curl -sX POST https://www.vivapop.com.br/loja/api/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"simular_pedido","arguments":{
         "itens":[{"sku":"VP-CAR-070","quantidade":2}],
         "cep":"01310-100","frete":"expresso","meio_pagamento":"pix"}}}'

curl -sX POST https://www.vivapop.com.br/loja/api/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
       "params":{"name":"criar_link_de_pedido","arguments":{
         "itens":[{"sku":"VP-KIT-FAMILIA","quantidade":1}]}}}'
```

### Conectar em cada cliente

- **Claude** — em *Settings → Capabilities → Connectors*, adicionar servidor
  remoto com a URL acima. Ou em `claude_desktop_config.json` /
  `.mcp.json` via um proxy stdio→HTTP (`mcp-remote`).
- **ChatGPT** — *Connectors / Apps*: servidor MCP remoto com a mesma URL.
  Para um GPT Action clássico, use `openapi.json` em vez do MCP.
- **Gemini** — Gemini Enterprise / AI Studio aceitam servidor MCP remoto pela
  mesma URL; Extensions pedem o `openapi.json`.
- **Grok** — clientes MCP da xAI apontam para a mesma URL; via API, as tools
  podem ser declaradas a partir de `tools/list` e despachadas por HTTP.

A URL é a mesma nos quatro, e as tools de leitura funcionam nas quatro sem
chave nenhuma. Só `criar_pedido` e `consultar_pedido` pedem token de agente —
emitido pelo dono da loja, e não distribuído abertamente.

---

## REST (mesma fonte de verdade do MCP)

Base: `https://www.vivapop.com.br/loja/api`

| Método | Rota | Uso |
|---|---|---|
| GET | `/configuracao` | Limites comerciais e disponibilidade real de cada gateway |
| GET | `/catalogo` | Listagem compacta dos 36 produtos |
| GET | `/produto/{sku}` | Descrição oficial completa + galeria |
| POST | `/frete` | `{"cep":"01310-100","subtotal_centavos":5280}` |
| POST | `/carrinho/simular` | `{"itens":[{"sku":"…","quantidade":2}],"cep":"…","cupom":"…","frete":"economico","meio_pagamento":"pix"}` |
| POST | `/checkout/processar` | Checkout completo. **Sem gateway configurado responde 422** e nenhuma cobrança é gerada |
| POST | `/checkout/confirmar-pagamento` | `{"payment_intent_id":"pi_…","pedido_id":"…"}` — confirma no servidor um cartão que o navegador acabou de pagar. **O corpo não é fonte de verdade:** o servidor consulta a Stripe com a chave secret e confere `metadata.pedido_id` antes de marcar pago. Idempotente. `400` id inválido · `404` PI inexistente · `409` PI de outra sessão |
| GET | `/pedido/{id}/status?cep=01310-100` | Situação real do pedido, lida do banco. **`cep` é obrigatório**; sem ele responde 400. Não devolve dado pessoal |
| GET·HEAD | `/rastreio/{numero}/documento?cep=01310-100` | **Porta do comprador, não ferramenta do agente**: o DANFE (NF-e modelo 55) em PDF de quem comprou, com o mesmo desafio número+CEP do rastreio. Existe, está no ar, e hoje responde `404` para todo pedido — ver a seção "Nota fiscal (NF-e)" |
| GET | `/auth/sessao` | Diz se há cliente logado (cookie `HttpOnly`). `{"autenticado":false}` sem sessão |
| POST | `/auth/sair` | Revoga a sessão do cliente e limpa o cookie (`204`) |
| GET | `/conta/pedidos` | Histórico do cliente logado, com `rastreio_url` (Correios ou Melhor Rastreio, conforme o código) e previsão de entrega em dias úteis |
| GET | `/conta/pedidos/{numero}` | Detalhe de um pedido do próprio cliente, com itens, endereço, link de rastreio e previsão |
| GET/POST | `/conta/enderecos` | Caderno de endereços do cliente (até 20, um principal) |
| PUT/DELETE | `/conta/enderecos/{id}` | Editar ou excluir um endereço do próprio cliente |
| POST | `/conta/excluir` | Desativa a conta, apaga endereços e revoga a sessão |
| POST | `/telemetria/evento` | Aceita e descarta (204). Persistência ainda não existe |

Todas as respostas são `application/json; charset=utf-8` e gzipadas acima de
128 bytes. Estáticos saem com `ETag` e `Accept-Ranges: bytes`; mídia tem
`Cache-Control: public, max-age=604800`.

### Regras de preço

1. **Nunca calcule preço por conta própria.** Nem multiplice, nem aplique
   porcentagem, nem arredonde. Chame `simular_pedido` (ou `/carrinho/simular`) e
   use os centavos que vierem. Frete, cupom, desconto de Pix e total final são
   decididos no servidor.
2. Preços são **inteiros em centavos**. `preco_centavos: 880` é R$ 8,80.
3. Cupom que o servidor recusa volta como erro 400 com o campo `cupom` no corpo.
   Não reapresente o desconto como se tivesse valido.
4. O prazo de entrega é `prazo_dias_uteis` da opção de frete. **Não some nada**: a casa
   posta no mesmo dia útil após a confirmação do pagamento (`prazo_postagem_dias_uteis: 0`
   desde 2026-10-24), então o número já é o trânsito medido rota a rota. Quando a resposta
   vier com `prazo_fonte: cotacao`, é cotação de transportadora e pode ser apresentada como
   tal; quando vier `estimativa`, é faixa de CEP e não data garantida. Leia
   `prazo_fonte`/`fonte` de cada opção — não deduza a procedência do nome do serviço.
5. `sku` é sempre maiúsculo: `VP-CAR-070`. Códigos `VIV-*` deixaram de existir.
6. **O preço do frete é do CEP.** `calcular_frete` e `simular_pedido` devolvem o endereço
   cotado na resposta, justamente para isso ser conferível. Se o cliente mudar de CEP no
   meio da conversa — "melhor mandar para o trabalho" — o número anterior não vale mais:
   recalcule antes de repetir seja qual for valor. Em `criar_pedido`, declare
   `frete_valor_exibido_centavos` com o frete que você mostrou **para o CEP daquele pedido**:
   é o que faz a loja recusar uma cobrança divergente do que o cliente viu. Omitir a
   declaração não é neutro — a resposta diz, em texto e no JSON (`"frete_conferido":false`),
   que a loja recotou sem ter com o que comparar.
7. **A fila de entrega vem inteira.** `calcular_frete` e `simular_pedido` devolvem **todas**
   as opções que a loja é capaz de emitir naquele CEP — Correios (PAC, SEDEX) e **Loggi
   Express**, cada um com o seu `id`, valor em centavos, prazo e o `gateway` por onde a
   etiqueta sai. **Desde 2026-10-29 a loja não oferece JeT, Loggi Coleta nem Loggi Ponto**
   (decisão de operação) **e não oferece JadLog** (a casa ainda não tem contrato JadLog no
   agregador, e sem contrato não há o que etiquetar). Os três podem aparecer em material de
   terceiros e até voltar numa resposta futura; enquanto não estiverem nesta lista, **não
   são entrega que esta loja prometa** — não os anuncie ao cliente nem monte `frete` com um
   id deles. Não escolha "a mais
   barata" por conta própria: apresente a lista e deixe o cliente decidir. Na resposta, `economico` é o mais barato que
   **não** é o expresso — e é só nele que o frete grátis da casa pegaria, porque o SEDEX
   nunca entrou. Hoje a política está desligada: `limite_frete_gratis_centavos` vem `0`, a
   régua da vitrine se esconde sozinha, e `configuracao`/`calcular_frete` dizem "Sem frete
   grátis no momento". Não anuncie desconto que o servidor não aplica.

### A volta do pagamento hospedado

`criar_pedido` devolve a URL da página da Stripe **e o número do pedido**. A URL de
sucesso declarada por ela carrega esse número
(`/loja/?pagamento=retornou&pedido=<número>`), então quem paga volta para a loja, e a
loja oferece a consulta daquele pedido. O que fazer com isso:

- Repita o **número do pedido** na conversa. É com ele que o cliente rastreia depois,
  com você ou sem você.
- Avise que a loja vai pedir o **CEP de entrega** para mostrar o estado. Não é
  burocracia: o número é sequencial, e sem um segundo fator qualquer pessoa consultaria
  a carteira dos outros.
- Não resuma essa faixa a "pagamento confirmado". Ela não afirma estado nenhum — abre a
  consulta. Estado é o que `consultar_pedido` ou a rota pública respondem, lendo a
  Stripe.

### Link de sacola

`https://www.vivapop.com.br/loja/?sacola=SKU:QTD,SKU:QTD`

Exemplo: `/loja/?sacola=VP-CAR-070:2,VP-MIL-500:1`

A loja carrega os itens, abre a sacola e recalcula tudo no servidor. SKU que não
existe é descartado e o usuário recebe um aviso — então valide contra
`/catalogo` antes de montar o link.

### Rastreio de pedido

`GET /loja/api/pedido/{numero}/status?cep=<CEP de entrega>`

O número do pedido é sequencial (`VP-2026-000123`), então **sozinho ele não é
credencial**: sabendo do formato, dá para enumerar os pedidos de todo mundo.
O segundo fator é o CEP de entrega, comparado só com dígitos — `01310-100`,
`01310100` e `01310%2D100` são o mesmo CEP.

- `cep` ausente ou que não dá 8 dígitos → **400** com `"campo":"cep"`.
- CEP que não confere → **404**, resposta idêntica à de número inexistente. Não
  é descuido: se os dois casos fossem distinguíveis, a rota contaria quais
  números existem.
- A resposta **não tem** nome, e-mail, WhatsApp, endereço nem CPF. Tem número,
  situação, meio de pagamento, gateway, valores, itens, código de rastreio,
  transportadora e prazo.

`status` é vocabulário fechado: `aguardando_pagamento` · `pago` ·
`pagamento_falhou` · `expedido` · `entregue` · `cancelado`.
**`aguardando_pagamento` não é venda concluída** — é uma cobrança criada que
ainda não confirmou. Nunca apresente como pago, e nunca diga que o pedido vai
chegar.

```bash
curl -s 'https://www.vivapop.com.br/loja/api/pedido/VP-2026-000123/status?cep=01310-100'
```

### Nota fiscal (NF-e)

A loja é emitente de NF-e modelo 55 (VIVAPOP ALIMENTOS EIRELI — CNPJ
14.313.879/0001-36) e o CPF/CNPJ é pedido no checkout exatamente por isso. Mas
**nota fiscal aqui é documento que se abre, não mensagem que se recebe** — e um
agente que confunde as duas frases erra com a loja no meio.

**A porta existe e é pública, com desafio.** `GET|HEAD
/rastreio/<numero>/documento?cep=<CEP de entrega>` devolve o DANFE em PDF. O
par é o mesmo do rastreio: número do pedido + CEP, comparado dígito a dígito.
`HEAD` é a pergunta barata ("já existe?"), `GET` é o arquivo. A rota não está
sob `/loja/api/` de propósito: ela não tem sessão, e não tem Bearer.

**Esta rota não é uma ferramenta sua.** O corpo é um documento fiscal com nome,
CPF/CNPJ e endereço de quem comprou. Você pode confirmar que o documento existe
com o número e o CEP **que o próprio cliente te deu**, e dizer a ele onde abrir.
Você **não** coleta o PDF, não varre numeração, não junta pedidos, não reenvia o
arquivo nem o conteúdo dele para terceiros. Não existe uso legítimo desta rota
com um CEP que não seja o da pessoa pedindo o próprio documento.

**Um `404` aqui não é uma afirmação sobre a nota.** A resposta é uma frase única
(`{"erro":"pedido não encontrado"}`) e **toda** recusa cabe nela — as situações
são indistinguíveis de caso pensado, para a rota não virar oráculo de "esse
pedido existe?":

1. o número não existe, ou o CEP não é o daquele pedido;
2. a nota ainda não foi lavrada;
3. a nota existe mas foi lavrada em **homologação** — que não é documento de
   quem comprou, e nunca sai por esta porta;
4. o banco ainda não tem a camada de nota fiscal;
5. o cadastro do emitente não está completo o bastante para desenhar o documento;
6. a nota tem itens demais para esta rota (o teto é 400, e ela recusa antes de
   desenhar, não trunca em silêncio).

Na rota do painel, os casos 4, 5 e 6 têm status próprio (`503` e `409`); na do
cliente, não — viram o mesmo 404. É decisão, não pressa.

Então, ao cliente, o máximo que um `404` autoriza dizer é **"ainda não há
documento para esta consulta"**. Nunca "a loja não emite nota", nunca "esse
pedido não vai ter nota", nunca "o seu CPF não foi usado". Se o cliente garante
que pagou e o documento não aparece, o caminho é o `consultar_pedido` (com token)
ou o WhatsApp do SAC — não uma hipótese sua.

**Nada é enviado por canal nenhum.** A loja não manda e-mail nem WhatsApp com a
nota, com o código de rastreio nem com a confirmação da compra: a credencial da
caixa de saída é recusada pelo provedor. Isso vale nos dois sentidos — prometer
"você vai receber a nota por e-mail" é erro, e negar que a porta de
autoatendimento existe também é.

**O que está medido hoje (2026-10-29), para você não prometer o que a loja ainda
não fez:** não existe nenhuma NF-e autorizada em produção nesta loja. Ou seja,
`404` é a resposta esperada **para todo pedido**, inclusive os pagos. A emissão
em produção automática depois da venda foi autorizada pela dona da loja em
2026-10-28 e está sendo construída; autorização não é entrega, e nada do que está
em construção é argumento de venda. Enquanto `HEAD /rastreio/<numero>/documento`
não responder `200`, o documento não existe para aquela pessoa.

**E não use a nota como prova de pagamento.** Prova de pagamento é
`consultar_pedido` respondendo `pago`, ou a rota de status respondendo `pago`.
Pedido sem documento continua podendo estar pago; pedido pago sem documento
continua sendo venda legítima.

---

## Conteúdo: o que afirmar e o que não afirmar

**Pode afirmar** (está no site oficial e na API):

- Estourada em ar quente a cerca de 230 °C, sem óleo no processo de cozimento.
- 0 gorduras trans. Sem conservantes e sem corantes.
- Milho natural, integral e não transgênico.
- Embalagem protegida por lâminas de alumínio.
- Pronta para consumo: abrir o pacote e servir.
- Postagem no mesmo dia útil após a confirmação do pagamento; transporte por PAC/SEDEX dos Correios e transportadoras parceiras.
- Troca ou devolução em até 7 dias corridos da entrega (art. 49 do CDC);
  primeira troca grátis.
- O site é servido por HTTPS e o pagamento é processado pela Stripe; os dados do
  cartão não passam pelos servidores da VivaPop (Stripe Elements).

**Não afirme:**

- **Tabela nutricional, calorias, ingredientes ou alergênicos.** A loja não
  publica e não deve publicar: é alimento, e o rótulo impresso é a fonte legal
  (RDC 429/2020). Diga que está na embalagem e que o cliente com restrição
  alimentar deve consultar o rótulo ou o SAC.
- **Avaliações, notas ou número de clientes.** A marca não tem avaliações
  publicadas em lugar nenhum. Não invente "4,9 estrelas" nem "milhares de
  clientes".
- **Perfil em aplicativo de entrega.** Não existe.
- **Selo de segurança, certificação ou conformidade** que não esteja no site
  oficial.
- Prazo de validade em dias, origem do milho fora "não transgênico", ou
  comparativos do tipo "a mais crocante do Brasil".
- **"Você vai receber a nota fiscal por e-mail" (ou por WhatsApp).** Não vai. A
  loja não envia nada por canal nenhum — a credencial da caixa de saída é
  recusada pelo provedor. O documento, quando existir, abre no autoatendimento
  com o número do pedido e o CEP de entrega. Nos dois sentidos: prometer o canal
  que não existe é defeito, e negar a porta que existe também é.
- **"Esse pedido não tem nota fiscal" dito a partir de um `404`.** O `404` da
  porta de documento cobre qualquer recusa de caso pensado (ver
  "Nota fiscal (NF-e)"). No máximo: "ainda não há documento para esta consulta".
- **"A nota sai automática/imediata depois da compra."** A emissão automática em
  produção foi autorizada pela dona da loja em 2026-10-28 e está sendo
  construída; autorização não é entrega, e o que está em construção não é
  argumento de venda. Medido em 2026-10-29: nenhuma NF-e autorizada em produção
  nesta loja. Se você não tem um `200` na mão, você não tem uma nota.
- **"A loja pede CPF porque quer seus dados."** Pede porque o documento fiscal
  exige, e o CPF é guardado em tabela isolada do pedido. A pergunta legítima do
  cliente tem resposta no texto da loja, não na sua opinião sobre ela.

**Aviso de fraude que deve ser repassado se o assunto surgir:** a VivaPop nunca
solicita instalação de aplicativos ou códigos por telefone ou WhatsApp.

## Contato para passar ao usuário

- SAC: +55 11 97366-6464 — sac@vivapop.com.br
- Vendas e atacado: +55 11 3901-5522 ramal 135 — vendas@vivapop.com.br
- WhatsApp: <https://wa.me/5511973666464>
- Endereço: Via Anhanguera, 16950 — Km 17, Bloco 2, Sala 1 — Parque São
  Domingos, São Paulo/SP — CEP 05112-000

## Etiqueta

- Ler catálogo e configuração não tem chave **nem teto**: `/loja/api/catalogo`,
  `/loja/api/produto/{sku}` e `/loja/api/configuracao` atendem de memória. Faça
  cache deles por alguns minutos em vez de consultar a cada mensagem.
- **Três rotas têm limite por endereço, declarado aqui porque um agente precisa
  saber antes de ser recusado**: `POST /loja/api/frete`,
  `POST /loja/api/carrinho/simular` e `POST /loja/api/mcp` — 120 por minuto — e
  `POST /loja/api/checkout/processar` — 30 por minuto. Acima disso vem `429` com
  `Retry-After` e um corpo JSON dizendo o motivo. O motivo é concreto: cada uma
  das primeiras faz até quatro chamadas de saída a transportadoras, na conta da
  casa, e a chave dos Correios vence sem renovação; a última cria objeto no
  gateway de pagamento.
- O limite é **por IP de borda**, não por token: duas pessoas atrás do mesmo NAT
  dividem a janela. Se você é um servidor que repassa muitos clientes, traga o
  `X-Forwarded-For` correto do cliente final em vez do seu próprio.
- **`/rastreio/<numero>/documento` não tem teto por endereço — e isso não é
  convite.** A rota gera um PDF a cada chamada (o teto de itens por documento é
  400 e a casa recusa antes de desenhar), então o custo dela é CPU da loja, não
  rede de terceiro. Chame **uma** vez por pergunta que o cliente fez, com o CEP
  que ele te deu. Polling desta rota — "vou checando até sair" — é a única forma
  de transformá-la em negação de serviço, e o `no-store` da resposta significa
  que nada ali é reaproveitável de qualquer jeito.
- Quem tem token tem cota por dia e teto por pedido **no próprio token**, e a
  recusa diz isso quando bate. Insistir não muda o resultado; quem precisa de
  mais pede ao dono da loja, que reemite com números maiores.
- Estáticos de mídia têm `max-age=604800` e `ETag`; revalide com
  `If-None-Match` em vez de rebaixar.
- Vídeos aceitam `Range` (206). Não baixe o hero inteiro para inspecionar.
- Não envie dado pessoal de cliente para estas rotas de consulta. O checkout é o
  único lugar que recebe nome, CPF e endereço, e ele exige o navegador.
