# Cozimax — API de revendas

> Revendas Cozimax mais próximas de um CEP. Base: https://api.cozimax.online/v1. Autenticação: header `x-api-key`.

Revendas Cozimax mais próximas de um CEP — a mesma lista que o atendimento da Cozimax no
WhatsApp envia ao consumidor. A lista de revendas é atualizada uma vez por dia.

## Autenticação

Toda chamada a `/v1/revendas` leva a chave de API no header `x-api-key` (ou
`Authorization: Bearer <chave>`). A chave é fornecida pela Cozimax, uma por parceiro, e deve
ficar no seu servidor: não a coloque em código que roda no navegador ou no celular do usuário.

## Limite de chamadas

Cada chave tem um teto por minuto (padrão: 60). Toda resposta traz `RateLimit-Limit` e
`RateLimit-Remaining`. Passou do teto: `429`, com `Retry-After` dizendo em quantos segundos
tentar de novo.

## Como ler a resposta

- **`localizacao.precisao`**: `rua` quando o CEP foi localizado no endereço; `centro_da_cidade`
  quando só a cidade foi encontrada. No segundo caso as distâncias contam do centro da cidade,
  não da casa do consumidor — diga isso a ele em vez de apresentar a lista como "as mais perto
  de você".
- **`todas_distantes`**: `true` quando nenhuma revenda fica a até 60 km. A lista traz então só as
  mais próximas (até 3), que podem estar longe.
- **`revendas` pode vir vazia ou com menos itens que o `limite`**: a lista só inclui revendas a
  até 60 km quando existe alguma nesse raio. Lista curta não significa que a Cozimax não tem
  outras revendas na região.
- **`distancia_km`** é em linha reta, não por estrada.
- **`id`** identifica a revenda de forma estável entre chamadas. Não é o CNPJ.

## Endpoint

`GET https://api.cozimax.online/v1/revendas`

### Parâmetros

| parâmetro | obrigatório | tipo | descrição |
|---|---|---|---|
| `cep` | sim | string | CEP com 8 dígitos, com ou sem hífen. |
| `limite` | não | integer (padrão 5, 1 a 10) | Quantas revendas devolver no máximo. |

### Exemplos de chamada

curl:

```shell
curl -s "https://api.cozimax.online/v1/revendas?cep=01310-100&limite=5" \
  -H "x-api-key: $COZIMAX_API_KEY"
```

JavaScript:

```javascript
const resposta = await fetch("https://api.cozimax.online/v1/revendas?cep=01310-100&limite=5", {
  headers: { "x-api-key": process.env.COZIMAX_API_KEY },
});
if (resposta.status === 429) {
  const espera = Number(resposta.headers.get("Retry-After"));
  // aguarde `espera` segundos antes de tentar de novo
}
const dados = await resposta.json();
for (const r of dados.revendas) console.log(r.nome, r.distancia_km, "km");
```

Python:

```python
import os, requests

resposta = requests.get(
    "https://api.cozimax.online/v1/revendas",
    params={"cep": "01310-100", "limite": 5},
    headers={"x-api-key": os.environ["COZIMAX_API_KEY"]},
    timeout=30,
)
resposta.raise_for_status()
for r in resposta.json()["revendas"]:
    print(r["nome"], r["distancia_km"], "km")
```

### Resposta 200

| campo | tipo | descrição |
|---|---|---|
| `cep` | string | O CEP consultado, formatado. |
| `localizacao` | objeto | Onde o CEP foi localizado. |
| `localizacao.cidade` | string ou null |  |
| `localizacao.uf` | string ou null |  |
| `localizacao.precisao` | string (rua, centro_da_cidade) | `centro_da_cidade`: não foi possível localizar a rua do CEP, só a cidade. As distâncias contam a partir do centro da cidade, não do endereço do consumidor. |
| `revendas[]` | lista |  |
| `revendas[].id` | string | Identificador estável da revenda (não é o CNPJ). |
| `revendas[].nome` | string | Nome fantasia; a razão social quando não há nome fantasia. |
| `revendas[].endereco` | objeto |  |
| `revendas[].endereco.logradouro` | string ou null |  |
| `revendas[].endereco.numero` | string ou null |  |
| `revendas[].endereco.bairro` | string ou null |  |
| `revendas[].endereco.cidade` | string |  |
| `revendas[].endereco.uf` | string |  |
| `revendas[].latitude` | number |  |
| `revendas[].longitude` | number |  |
| `revendas[].distancia_km` | number | Distância em linha reta, em km, com uma casa decimal. |
| `revendas[].maps_url` | string | Link do Google Maps para a localização da revenda. |
| `revendas[].parcela_12x` | boolean | A revenda parcela em até 12x no cartão. |
| `todas_distantes` | boolean | true quando nenhuma revenda fica a até 60 km; a lista traz então só as mais próximas. |

Exemplo:

```json
{
  "cep": "01310-100",
  "localizacao": {
    "cidade": "São Paulo",
    "uf": "SP",
    "precisao": "rua"
  },
  "revendas": [
    {
      "id": "fc48c5c5a1c0cab6",
      "nome": "OBRAMAX ATACADO DE CONSTRUCAO",
      "endereco": {
        "logradouro": "AV DO ESTADO",
        "numero": null,
        "bairro": "MOOCA",
        "cidade": "São Paulo",
        "uf": "SP"
      },
      "latitude": -23.5600373,
      "longitude": -46.6108872,
      "distancia_km": 4.4,
      "maps_url": "https://www.google.com/maps/search/?api=1&query=-23.5600373,-46.6108872",
      "parcela_12x": false
    }
  ],
  "todas_distantes": false
}
```

### Erros

Todo erro vem como `{ "erro": "<código>", "mensagem": "<texto em português>" }`. Trate pelo `erro`; a `mensagem` pode mudar.

| status | quando |
|---|---|
| 400 | CEP ou limite inválido (`cep_invalido`, `limite_invalido`). |
| 401 | Chave ausente (`chave_ausente`), inválida ou revogada (`chave_invalida`). |
| 404 | CEP não encontrado (`cep_nao_encontrado`). |
| 429 | Limite de chamadas por minuto excedido (`limite_excedido`). O header Retry-After diz em quantos segundos tentar de novo; toda resposta traz RateLimit-Limit e RateLimit-Remaining. |
| 502 | Falha temporária do serviço (`origem_indisponivel`). Tente novamente. |
| 503 | Serviço indisponível (`indisponivel`), inclusive quando a consulta de CEP ou a validação da chave está fora do ar. Não significa que a chave ou o CEP estejam errados. |
| 504 | A busca demorou demais (`tempo_esgotado`). Tente novamente. |

### Headers da resposta

| header | significado |
|---|---|
| `RateLimit-Limit` | teto de chamadas por minuto da sua chave |
| `RateLimit-Remaining` | quantas ainda cabem no minuto atual |
| `Retry-After` | só no 429: segundos até poder tentar de novo |
| `X-Cache` | `HIT` quando a resposta veio do cache da Cozimax (a lista muda uma vez por dia) |

## Boas práticas para integrar

- Chame a API do seu servidor. A chave dá acesso à sua cota e não deve ir para navegador ou aplicativo.
- Pode guardar a resposta de um CEP por até 24 horas: a lista de revendas muda uma vez por dia.
- No 429, espere o `Retry-After` antes de repetir. No 502, 503 e 504, repita com espera crescente.
- Mostre a distância como aproximada (linha reta) e, quando `precisao` for `centro_da_cidade`, avise que ela conta do centro da cidade.
- Não conclua que não há revenda na região porque a lista veio curta ou vazia.
