# Tudo Envio — Exemplos de Payload (API v1)

Base URL (produção): `https://tudoenvio.com.br/api/public/v1`
Base URL (preview): `https://project--76c9d2f7-2e09-49c2-af7b-c8cbf169b23f-dev.lovable.app/api/public/v1`

Autenticação em todas as chamadas:

```http
Authorization: Bearer te_live_SEU_TOKEN
Content-Type: application/json
X-Device: TOTEM-001            # opcional, aparece no terminal de logs
Idempotency-Key: 550e8400-...  # recomendado nas emissões
```

Formato de resposta:

```json
{ "success": true, "...": "dados" }
{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "..." } }
```

---

## 1. `GET /me` — dados do token

Sem body. Retorna usuário/empresa e plano vinculados ao token.

---

## 2. `POST /frete/cotacao` — cotar e listar opções

```json
{
  "cep_origem": "01001000",
  "cep_destino": "20040002",
  "peso": 1.2,
  "comprimento": 20,
  "largura": 15,
  "altura": 10,
  "valor_declarado": 4500,
  "seguro": true,
  "mao_propria": false,
  "aviso_recebimento": true,
  "embalagens": [{ "id": "b3f1c2a4-1111-2222-3333-444455556666", "quantidade": 1 }]
}
```

Variantes aceitas: `peso_gramas` (em vez de `peso`), `comprimento_cm` / `largura_cm` / `altura_cm`,
`adicionais: ["seguro","mao_propria","aviso_recebimento"]` em vez das flags booleanas,
`servico: "SEDEX"` ou `codigo_servico: "03220"` para filtrar uma única opção.

Resposta completa (campo a campo):

```json
{
  "success": true,
  "payload": {
    "cep_origem": "01001000",
    "cep_destino": "20040002",
    "peso": 1.2,
    "comprimento": 20,
    "largura": 15,
    "altura": 10,
    "valor_declarado": 4500,
    "seguro": true,
    "aviso_recebimento": true,
    "embalagens": [{ "id": "b3f1c2a4-1111-2222-3333-444455556666", "quantidade": 1 }]
  },
  "recebido": { "...": "igual a payload (alias de compatibilidade)" },
  "payload_normalizado": {
    "cep_origem": "01001000",
    "cep_destino": "20040002",
    "peso_kg": 1.2,
    "comprimento_cm": 20,
    "largura_cm": 15,
    "altura_cm": 10,
    "valor_declarado": 4500,
    "servico": null,
    "codigo_servico": null,
    "adicionais": { "seguro": true, "mao_propria": false, "aviso_recebimento": true },
    "embalagens": [
      {
        "id": "b3f1c2a4-1111-2222-3333-444455556666",
        "nome": "Caixa P",
        "quantidade": 1,
        "preco_unitario": 3.5,
        "subtotal": 3.5
      }
    ]
  },
  "cotacoes": [
    {
      "servico": "SEDEX",
      "codigo_servico": "03220",
      "valor": 28.90,
      "prazo": 2,
      "erro": null,
      "adicionais": [{ "codigo": "seguro", "label": "Seguro (Valor Declarado)", "aplicado": true, "valor": 67.50, "icone": "seguro", "icone_url": "https://tudoenvio.com.br/api-assets/adicionais/seguro.svg" }],
      "total_adicionais": 76.00,
      "embalagens": [{ "id": "b3f1c...", "nome": "Caixa P", "quantidade": 1, "preco_unitario": 3.5, "subtotal": 3.5 }],
      "total_embalagens": 3.5,
      "valor_total": 108.40
    }
  ],
  "adicionais": [{ "codigo": "seguro", "label": "Seguro (Valor Declarado)", "aplicado": true, "valor": 67.50, "icone": "seguro", "icone_url": "https://tudoenvio.com.br/api-assets/adicionais/seguro.svg" }],
  "total_adicionais": 76.00,
  "embalagens": [{ "id": "b3f1c...", "nome": "Caixa P", "quantidade": 1, "preco_unitario": 3.5, "subtotal": 3.5 }],
  "total_embalagens": 3.5
}
```

Significado dos blocos:

| Campo | O que é |
| --- | --- |
| `payload` | **Cópia exata** do JSON que você enviou — nada é adicionado, removido ou renomeado. Use para conferência na tela do POS/totem. |
| `recebido` | Alias de `payload`, mantido para clientes antigos. |
| `payload_normalizado` | O que a API **realmente entendeu**: CEPs só com dígitos, `peso_kg` (converte `peso_gramas`), medidas em cm, flags de adicionais resolvidas e embalagens já com preço. Compare com `payload` para achar divergências. |
| `cotacoes[]` | Uma entrada por serviço: `servico`, `codigo_servico`, `valor` (frete), `prazo` (dias), `erro`, adicionais/embalagens aplicados e `valor_total` (frete + adicionais + embalagens). |
| `adicionais`, `total_adicionais` | Adicionais aplicados e soma, no topo da resposta. Cada item traz `icone` (nome curto) e `icone_url` (SVG público, ex.: `https://tudoenvio.com.br/api-assets/adicionais/seguro.svg`) para exibir no POS/totem. |
| `embalagens`, `total_embalagens` | Embalagens resolvidas e soma, no topo da resposta. |
| `pagamento_pix` | Presente **somente** quando o request traz `pagamento: "pix"` (ver seção “PIX na cotação”). |


---

## 3. `POST /frete/adicionais` — só os serviços adicionais

Cada adicional retornado inclui `icone` e `icone_url` (SVG público). Ícones disponíveis:
`/api-assets/adicionais/seguro.svg`, `/api-assets/adicionais/mao-propria.svg`, `/api-assets/adicionais/aviso-recebimento.svg`.

```json
{
  "valor_declarado": 4500,
  "seguro": true,
  "mao_propria": false,
  "aviso_recebimento": true
}
```

---

## 4. `POST /frete/total` — valor final do envio

Modo A — já tenho o frete escolhido:

```json
{
  "valor_frete": 32.50,
  "valor_declarado": 4500,
  "seguro": true,
  "aviso_recebimento": true,
  "embalagens": [{ "id": "b3f1c2a4-1111-2222-3333-444455556666", "quantidade": 2 }]
}
```

Modo B — a API cota e devolve o total:

```json
{
  "cep_origem": "01001000",
  "cep_destino": "20040002",
  "peso": 1.2,
  "comprimento": 20,
  "largura": 15,
  "altura": 10,
  "codigo_servico": "03220",
  "valor_declarado": 4500,
  "seguro": true
}
```

---

## 5. `POST /pos/etiquetas` — emissão na maquininha (POS)

Payload completo (canônico):

```json
{
  "teste": false,
  "envio": {
    "cotacao": {
      "servico": "SEDEX",
      "codigoServico": "03220",
      "precoBase": 28.90,
      "precoFinal": 40.46,
      "prazoDias": 2,
      "extras": { "seguro": true, "aviso": true, "maos": false },
      "extrasPrice": 15.08,
      "cepOrigem": "01001000",
      "cepDestino": "20040002",
      "peso": "1.2",
      "altura": "10",
      "largura": "15",
      "comprimento": "20"
    },
    "remetente": {
      "nome": "Tudo Envio Loja Centro",
      "documento": "12345678000195",
      "telefone": "11999998888",
      "email": "loja@tudoenvio.com.br",
      "cep": "01001000",
      "logradouro": "Praça da Sé",
      "numero": "100",
      "complemento": "Loja 3",
      "bairro": "Sé",
      "cidade": "São Paulo",
      "uf": "SP"
    },
    "destinatario": {
      "nome": "Maria Souza",
      "documento": "39053344705",
      "telefone": "21988887777",
      "email": "maria@exemplo.com",
      "cep": "20040002",
      "logradouro": "Av. Rio Branco",
      "numero": "156",
      "complemento": "Sala 1201",
      "bairro": "Centro",
      "cidade": "Rio de Janeiro",
      "uf": "RJ"
    },
    "itens": [
      { "descricao": "Camiseta algodão", "quantidade": 2, "valor": 45.00 },
      { "descricao": "Boné", "quantidade": 1, "valor": 35.00 }
    ],
    "embalagens": [
      {
        "id": "b3f1c2a4-1111-2222-3333-444455556666",
        "nome": "Caixa P",
        "precoCentavos": 350,
        "quantidade": 1
      }
    ],
    "embalagensPrice": 3.50,
    "logisticaReversa": false
  },
  "pagamento_externo": {
    "nsu": "000123456789",
    "tid": "000123456789",
    "tipo": "credito",
    "bandeira": "VISA",
    "parcelas": 1,
    "valor": 59.04,
    "autorizacao": "A1B2C3",
    "pan_masked": "**** **** **** 1234",
    "adquirente": "CIELO"
  }
}
```

> `pagamento_externo.valor` deve ser igual a `cotacao.precoFinal + cotacao.extrasPrice + embalagensPrice`.
> `tipo` aceita: `credito`, `debito`, `pix`, `dinheiro`, `voucher`.

### 5.1 Retorno bruto do SDK Android (aceito diretamente)

```json
{
  "envio": { "...": "igual ao exemplo acima" },
  "pagamento_externo": {
    "result": true,
    "error": false,
    "finalResult": "APPROVED",
    "codeResult": 0,
    "message": "Transação aprovada",
    "nsuAcquirer": "000123456789",
    "authCode": "A1B2C3",
    "typeCard": "CREDIT",
    "brand": "MASTERCARD",
    "acquirerName": "CIELO",
    "panMasked": "**** **** **** 4321",
    "amount": 5904,
    "date": 1785000000000
  }
}
```

`amount` vem em centavos e é convertido automaticamente; `nsuAcquirer`, `typeCard`,
`brand`, `authCode` e `panMasked` são mapeados para os campos canônicos.

### 5.2 Emissão de teste (não debita, não emite etiqueta real)

```json
{
  "teste": true,
  "envio": { "...": "igual ao exemplo acima" },
  "pagamento_externo": { "nsu": "TESTE-0001", "tipo": "debito", "valor": 59.04 }
}
```

### 5.3 Resposta da emissão (JSON usado para imprimir no POS)

O objeto `etiqueta.recibo` é **exatamente** o payload consumido pela lib de
impressão do totem/POS (schema `tudoenvio.recibo/v2`). Não é preciso baixar o
PDF: todos os campos já vêm formatados para renderizar em 58/80 mm.

A resposta da emissão (produção, teste e resposta idempotente) devolve **o mesmo
objeto de etiqueta** da lista `GET /v1/etiquetas` e da consulta
`GET /v1/etiquetas/{id}`: `codigo_servico`, `status`, `origem`,
`forma_pagamento`, `destinatario`, `etiqueta_pdf_url`, `declaracao_pdf_url`,
`etiqueta_completa_pdf_url` (combinado A6 etiqueta + declaração),
`recibo_pdf_url`, `recibo_json_url` e o objeto `recibo`. Se o combinado ou o
recibo ainda não existirem no storage, eles são gerados na hora da resposta.

O schema `v2` acrescenta (mantendo tudo do `v1`): endereço completo de
remetente e destinatário (`documento`, `telefone`, `email`, `cep`, `logradouro`,
`numero`, `complemento`, `bairro` e a linha pronta `enderecoLinha`),
`prepostagem.codigoServico`, `prepostagem.idPrepostagemCorreios`,
`prepostagem.dataPrevista`, a lista `embalagens`, `totais.embalagens` e
`extras.valores` (seguro, mão própria e AR discriminados). Recibos gerados antes
dessa versão são regenerados automaticamente na primeira consulta.

```json
{
  "success": true,
  "ambiente": "producao",
  "teste": false,
  "pago": true,
  "etiqueta": {
    "id": "9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21",
    "codigo_rastreamento": "AD743208829BR",
    "servico": "SEDEX",
    "codigo_servico": "03220",
    "status": "processada",
    "origem": "api_pos",
    "forma_pagamento": "pos_credito",
    "valor": 59.04,
    "created_at": "2026-07-31T18:42:10.512Z",
    "destinatario": {
      "nome": "Maria Souza",
      "cidade": "São Paulo",
      "uf": "SP",
      "cep": "01310100"
    },
    "etiqueta_pdf_url": "https://.../etiqueta.pdf?token=...",
    "declaracao_pdf_url": "https://.../declaracao.pdf?token=...",
    "etiqueta_completa_pdf_url": "https://.../etiqueta-declaracao-a6.pdf?token=...",
    "recibo_pdf_url": "https://.../recibo.pdf?token=...",
    "recibo_json_url": "/api/public/v1/etiquetas/9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21/recibo-json",
    "recibo": {
      "schema": "tudoenvio.recibo/v2",
      "geradoEm": "2026-07-31T18:42:11.004Z",
      "prepostagem": {
        "id": "9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21",
        "idCurto": "9F2C1E70",
        "idPrepostagemCorreios": "PRlCyNjcB2RGGHgfiyX7OxAQ",
        "createdAtIso": "2026-07-31T18:42:10.512Z",
        "servico": "SEDEX",
        "codigoServico": "03220",
        "formaPagamento": "pos_credito",
        "formaPagamentoLabel": "Cartão de Crédito",
        "pesoKg": 0.5,
        "dimensoesCm": { "altura": "5", "largura": "20", "comprimento": "30" },
        "cepOrigem": "14801000",
        "cepOrigemFormatado": "14801-000",
        "cepDestino": "01310100",
        "cepDestinoFormatado": "01310-100",
        "prazoDias": 2,
        "dataPrevista": "2026-08-04"
      },
      "rastreio": {
        "codigo": "AD743208829BR",
        "codigoFormatado": "AD 743 208 829 BR",
        "url": "https://tudoenvio.com.br/rastreio?codigo=AD743208829BR",
        "qrPayload": "https://tudoenvio.com.br/rastreio?codigo=AD743208829BR"
      },
      "remetente": {
        "nome": "Tudo Envio",
        "documento": "37526628000135",
        "telefone": "(16) 99116-5701",
        "email": null,
        "cep": "14801000",
        "cepFormatado": "14801-000",
        "logradouro": "Rua Exemplo",
        "numero": "100",
        "complemento": "Loja 2",
        "bairro": "Centro",
        "cidade": "Araraquara",
        "uf": "SP",
        "enderecoLinha": "Rua Exemplo, 100 - Loja 2 - Centro - Araraquara/SP - 14801-000"
      },
      "destinatario": {
        "nome": "Maria Souza",
        "documento": "12345678909",
        "telefone": "(11) 98888-7777",
        "email": null,
        "cep": "01310100",
        "cepFormatado": "01310-100",
        "logradouro": "Av. Paulista",
        "numero": "1000",
        "complemento": null,
        "bairro": "Bela Vista",
        "cidade": "São Paulo",
        "uf": "SP",
        "enderecoLinha": "Av. Paulista, 1000 - Bela Vista - São Paulo/SP - 01310-100"
      },
      "itens": [
        { "descricao": "Camiseta algodão", "quantidade": 2, "valorUnitario": 45, "valorTotal": 90 }
      ],
      "embalagens": [
        {
          "id": "5714b525-593f-426d-96c2-35f402901582",
          "nome": "Envelope Bolha Correios",
          "quantidade": 1,
          "valorUnitario": 11.9,
          "valorTotal": 11.9
        }
      ],
      "totais": {
        "frete": 43.64,
        "adicionais": 3.5,
        "embalagens": 11.9,
        "total": 59.04,
        "totalItensDeclarados": 90,
        "moeda": "BRL"
      },
      "extras": {
        "seguro": true,
        "valorDeclarado": 90,
        "maoPropria": false,
        "avisoRecebimento": false,
        "valores": { "seguro": 3.5, "maoPropria": 0, "avisoRecebimento": 0 }
      },
      "empresa": {
        "razaoSocial": "TUDO ENVIO - UP SERVIÇOS E PUBLICIDADE LTDA",
        "cnpj": "37526628000135",
        "inscricaoEstadual": "797609474119",
        "agencia": "AG: 00442465 - PONTO DE COLETA GUAPORÉ - SE/SPI",
        "contrato": "9912749862",
        "site": "www.tudoenvio.com.br"
      }
    }
  }
}
```


Como imprimir no POS:

1. `POST /api/public/v1/pos/etiquetas` → leia `etiqueta.recibo` da resposta.
2. Renderize os campos na ordem: cabeçalho (`empresa`), `prepostagem`,
   `remetente`/`destinatario`, `itens`, `totais`, `extras` e por último o QR
   Code com `rastreio.qrPayload` + `rastreio.codigoFormatado`.
3. Se precisar reimprimir depois, chame
   `GET /api/public/v1/etiquetas/{id}/recibo-json` (retorna `{ "recibo": { ... } }`).

> No modo teste (`teste: true` ou token `te_test_`) o mesmo objeto `recibo` é
> retornado, com código fictício `TT…BR`, permitindo testar a impressão sem
> emitir nos Correios.


---

## 6. `POST /etiquetas` — emissão com saldo pré-pago

Body = **apenas o objeto `envio`** do exemplo 5 (sem `pagamento_externo`):

```json
{
  "cotacao": { "...": "..." },
  "remetente": { "...": "..." },
  "destinatario": { "...": "..." },
  "itens": [{ "descricao": "Livro", "quantidade": 1, "valor": 60.00 }],
  "embalagens": [],
  "embalagensPrice": 0
}
```

Erro típico quando falta saldo:

```json
{
  "success": false,
  "error": { "code": "INSUFFICIENT_BALANCE", "message": "Saldo insuficiente. Saldo atual R$ 10.00 • necessário R$ 59.04." }
}
```

---

## 7. Consultas e utilitários

| Método | Endpoint | Body |
| --- | --- | --- |
| GET | `/etiquetas/{id}` | — |
| GET | `/etiquetas/{id}/pdf` | — (redireciona para PDF assinado) |
| POST | `/etiquetas/{id}/pdfs` | — (gera os PDFs faltantes e devolve as URLs) |
| POST | `/etiquetas/{id}/email` | `{ "email": "...", "anexos": ["recibo","combinado"] }` |

| GET | `/etiquetas/{id}/recibo-json` | — (payload de impressão) |
| GET | `/rastreamento/{codigo}` | — |
| GET | `/saldo` | — |
| GET | `/config/adicionais` | — |
| GET | `/config/embalagens` | — |
| GET | `/config/plano` | — |
| GET | `/clientes` | — |

### `POST /saldo/recarga`

```json
{ "valor": 150.00 }
```

### `POST /clientes`

```json
{
  "nome": "Maria Souza",
  "documento": "39053344705",
  "telefone": "21988887777",
  "email": "maria@exemplo.com",
  "cep": "20040002",
  "endereco": "Av. Rio Branco",
  "numero": "156",
  "complemento": "Sala 1201",
  "bairro": "Centro",
  "cidade": "Rio de Janeiro",
  "uf": "RJ"
}
```

---

## 8. Exemplo cURL ponta a ponta

```bash
TOKEN="te_live_SEU_TOKEN"
BASE="https://tudoenvio.com.br/api/public/v1"

# 1) cotar
curl -s -X POST "$BASE/frete/cotacao" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "X-Device: TOTEM-001" \
  -d '{"cep_origem":"01001000","cep_destino":"20040002","peso":1.2,
       "comprimento":20,"largura":15,"altura":10,
       "valor_declarado":4500,"seguro":true}'

# 2) emitir na maquininha
curl -s -X POST "$BASE/pos/etiquetas" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d @payload-pos.json
```

---

## 8.1 `GET /etiquetas` — lista com todas as URLs

`GET https://tudoenvio.com.br/api/public/v1/etiquetas?limit=20&status=`
(`limit` de 1 a 100, padrão 20). Cada item já traz as URLs assinadas dos
arquivos **e o objeto `recibo` completo** (o mesmo de `/etiquetas/{id}` e do JSON
enviado à impressora) — não é preciso chamar `/etiquetas/{id}` para
imprimir/reimprimir.


```json
{
  "success": true,
  "total": 1,
  "limit": 20,
  "etiquetas": [
    {
      "id": "9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21",
      "codigo_rastreamento": "AD743208829BR",
      "servico": "SEDEX",
      "codigo_servico": "03220",
      "status": "emitida",
      "origem": "api_pos",
      "forma_pagamento": "pos_credito",
      "valor": 59.04,
      "created_at": "2026-07-31T18:42:10.512Z",
      "destinatario": { "nome": "Maria Souza", "cidade": "Ribeirão Preto", "uf": "SP", "cep": "14020000" },
      "etiqueta_pdf_url": "https://.../etiqueta.pdf?token=...",
      "declaracao_pdf_url": "https://.../declaracao.pdf?token=...",
      "etiqueta_completa_pdf_url": "https://.../etiqueta-declaracao-a6.pdf?token=...",
      "recibo_pdf_url": "https://.../recibo.pdf?token=...",
      "recibo_json_url": "/api/public/v1/etiquetas/9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21/recibo-json",
      "recibo": { "tipo": "tudoenvio.recibo/v2", "...": "payload completo, igual ao de GET /etiquetas/{id}" }
    }
  ]

}
```

- `etiqueta_completa_pdf_url` é o **combinado A6** (etiqueta + declaração), o
  mesmo PDF enviado por e-mail. A partir de agora ele é gravado no storage na
  própria emissão, então vem preenchido nas etiquetas novas.
- Arquivos ainda não gerados vêm como `""` (string vazia) — caso típico de
  etiquetas antigas, emitidas antes dessa mudança.
- As URLs são assinadas e temporárias: gere de novo quando expirar.

### Recuperar PDFs em branco

`POST /api/public/v1/etiquetas/{id}/pdfs`

Gera sob demanda o que estiver faltando (combinado A6, combinado A4, recibo PDF
e recibo JSON) e devolve todas as URLs assinadas já preenchidas. Se os arquivos
já existirem, apenas devolve as URLs (resposta rápida).

```json
{
  "id": "9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21",
  "etiqueta_pdf_url": "https://.../etiqueta.pdf?token=...",
  "declaracao_pdf_url": "https://.../declaracao.pdf?token=...",
  "etiqueta_completa_pdf_url": "https://.../etiqueta-declaracao-a6.pdf?token=...",
  "etiqueta_completa_a4_pdf_url": "https://.../etiqueta-declaracao-a4.pdf?token=...",
  "recibo_pdf_url": "https://.../recibo.pdf?token=...",
  "recibo_json_url": "/api/public/v1/etiquetas/9f2c1e70-.../recibo-json",
  "avisos": []
}
```

Fluxo recomendado no POS: listar em `GET /etiquetas` e, se o campo que você vai
imprimir vier `""`, chamar `POST /etiquetas/{id}/pdfs` para aquele item.

### Enviar por e-mail (igual ao painel)

`POST /api/public/v1/etiquetas/{id}/email`

```json
{
  "email": "cliente@exemplo.com",
  "anexos": ["recibo", "combinado"]
}
```

- `email` obrigatório.
- `anexos` opcional; padrão `["recibo"]` (recibo 80mm). `combinado` anexa também
  o A6 (etiqueta + declaração).
- Arquivos ainda não gerados são criados sob demanda antes do envio.
- Token de teste (`te_test_…`) envia com `[TESTE]` no assunto.

Resposta:

```json
{
  "success": true,
  "id": "9f2c1e70-4a1b-4c33-9a2f-58d0b1c77e21",
  "enviado_para": "cliente@exemplo.com",
  "anexos": ["recibo", "combinado"]
}
```


---

## 9. Códigos de erro


| Código | HTTP | Significado |
| --- | --- | --- |
| `UNAUTHORIZED` | 401 | Token ausente, inválido ou revogado |
| `VALIDATION_ERROR` | 400 | JSON inválido ou campo fora do formato |
| `VALIDATION_ERROR` | 422 | Payload de envio incompleto (CPF/CNPJ, endereço, itens) |
| `INSUFFICIENT_BALANCE` | 402 | Saldo insuficiente (`POST /etiquetas`) |
| `NOT_FOUND` | 404 | Etiqueta/recurso não encontrado |
| `INTERNAL_ERROR` | 500 | Falha no processamento (ver `/admin/api-terminal`) |

---

## Ambiente do token (teste x produção)

O ambiente é identificado pelo **prefixo do token**:

| Prefixo | Ambiente | Comportamento |
| --- | --- | --- |
| `te_live_…` | produção | emissão real, debita saldo, cria pré-postagem nos Correios |
| `te_test_…` | teste (sandbox) | `POST /v1/pos/etiquetas` sempre roda em modo teste (sem saldo, sem Correios, código fictício `TT…BR`); `POST /v1/etiquetas` retorna 403 |

Como o app sabe que é teste:

1. Header em toda resposta autenticada: `x-tudoenvio-ambiente: teste | producao`
2. Campo no corpo: `"ambiente": "teste"` (em `/v1/me`, `/v1/pos/etiquetas`)
3. `GET /v1/me` → `{ "success": true, "ambiente": "teste", "teste": true, "user": { … } }`

Tokens gerados pelo botão “Gerar token de teste (admin)” são sempre `te_test_`.

---

## PIX na cotação (`POST /api/public/v1/frete/cotacao`)

Envie `pagamento: "pix"` junto com `remetente`, `destinatario` e `itens` para
receber a cobrança PIX já pronta para exibir/gerar no aparelho. É obrigatório
informar `servico` ou `codigo_servico` (uma única opção).

```json
{
  "cep_origem": "13560000",
  "cep_destino": "01310930",
  "peso": 1.2,
  "altura": 10,
  "largura": 20,
  "comprimento": 30,
  "codigo_servico": "03220",
  "valor_declarado": 150,
  "adicionais": ["seguro"],
  "pagamento": "pix",
  "remetente": {
    "nome": "Loja Exemplo LTDA",
    "documento": "12345678000199",
    "telefone": "16999999999",
    "email": "loja@exemplo.com.br",
    "cep": "13560000",
    "logradouro": "Rua Sete de Setembro",
    "numero": "100"
  },
  "destinatario": {
    "nome": "Maria Souza",
    "documento": "12345678909",
    "telefone": "11988887777",
    "cep": "01310930",
    "logradouro": "Av. Paulista",
    "numero": "1000"
  },
  "itens": [
    { "descricao": "Camiseta", "quantidade": 1, "valor": 150 }
  ]
}
```

Resposta (trecho):

```json
{
  "success": true,
  "cotacoes": [ { "servico": "SEDEX", "codigo_servico": "03220", "valor": 55.54, "valor_total": 58.04 } ],
  "pagamento_pix": {
    "pagamento_id": "365c0bb5-cc4a-4398-9d96-d957344b9e52",
    "payment_id": "1234567890",
    "qr_code": "00020126...6304ABCD",
    "qr_code_base64": "iVBORw0KGgoAAAANSUhEUg...",
    "ticket_url": "https://www.mercadopago.com.br/payments/1234567890/ticket",
    "valor": 58.04,
    "expira_em": "2026-01-01T12:30:00.000Z",
    "pago": false,
    "status": "pendente",
    "teste": false,
    "consulta_url": "/api/public/v1/pagamentos/pix/365c0bb5-cc4a-4398-9d96-d957344b9e52"
  }
}
```

Use `qr_code` (copia e cola) ou `qr_code_base64` (imagem PNG) para exibir no POS.
Com token de teste (`te_test_`) nenhuma cobrança real é criada — o `qr_code` é fictício.

## Consultar o PIX (`GET /api/public/v1/pagamentos/pix/{id}`)

```bash
curl https://tudoenvio.com.br/api/public/v1/pagamentos/pix/365c0bb5-cc4a-4398-9d96-d957344b9e52 \
  -H "Authorization: Bearer te_live_..."
```

Aguardando pagamento:

```json
{ "success": true, "pagamento_id": "365c...", "pago": false, "status": "pendente", "valor": 58.04, "erro": null, "etiqueta": null }
```

Pago e etiqueta emitida (a emissão é automática):

```json
{
  "success": true,
  "pagamento_id": "365c...",
  "payment_id": "1234567890",
  "pago": true,
  "status": "emitida",
  "valor": 58.04,
  "erro": null,
  "etiqueta": {
    "id": "…",
    "codigo_rastreamento": "TT663847134BR",
    "etiqueta_pdf_url": "https://…",
    "recibo_pdf_url": "https://…",
    "recibo": { "schema": "tudoenvio.recibo/v2" }
  }
}
```

Faça polling a cada 3–5s até `pago: true` e `etiqueta` diferente de `null`
(`status`: `pendente` → `pago`/`processando` → `emitida`).
