> ## Documentation Index
> Fetch the complete documentation index at: https://developers.zouti.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Autenticação

> Como enviar a chave de API, guardá-la, trocá-la e revogá-la.

Toda requisição se autentica com uma chave de API da conta, enviada no header `Authorization`:

```text theme={null}
Authorization: Bearer zt_live_...
```

<Warning>
  **Ainda não há modo de teste.** Não existe chave de teste nem ambiente de sandbox: toda chamada,
  com qualquer chave, lê dados reais de produção da conta.
</Warning>

## Enviar a chave

* **Só no header.** A chave nunca é aceita na query string (`?api_key=`, `?key=`, `?token=`).
  Uma requisição assim recebe `401`.
* **Exatamente como foi copiada.** Um espaço ou uma quebra de linha antes ou depois invalida a
  chave.
* **A conta é a dona da chave.** Não existe parâmetro de conta: nenhum caminho, query ou header
  troca a conta consultada. Para ler outra conta, use uma chave criada nela.

## Criar uma chave

A chave é criada no dashboard, em **Configurações → Chaves de API** → **Criar chave**, por um
administrador da conta.

* **Nome da chave**: diga onde ela é usada (`ERP`, `n8n`, `Planilha financeira`). O nome ajuda a
  saber qual chave revogar depois.
* **Expiração (opcional)**: no mínimo 1 hora a partir da criação. Sem data, a chave não expira.
* **Aparece uma única vez.** A chave é exibida só na criação, no painel **Chave de API criada**.
  A Zouti guarda apenas um hash e não consegue mostrá-la de novo. Perdeu a chave? Crie outra e
  revogue a antiga.
* **Cerca de 1 segundo para valer.** Se a primeira chamada logo depois da criação receber `401`,
  espere alguns segundos e repita.
* **Até 10 chaves ativas** por conta. Para criar a 11ª, revogue uma.

## Guardar a chave

Uma chave lê todos os recursos públicos da conta, inclusive os dados completos dos compradores:
nome, e-mail, telefone, CPF/CNPJ e endereço. Trate-a como uma senha.

* Guarde-a num cofre de segredos ou numa variável de ambiente do servidor (`ZOUTI_API_KEY`).
* Nunca a coloque em código de front-end, aplicativo móvel ou repositório de código.
* A API não tem CORS: chamadas feitas do navegador são bloqueadas. Chame a API só do seu servidor.
* Use uma chave por sistema. Assim, revogar a chave de um sistema não para os outros.

## Trocar a chave sem parar a integração

<Steps>
  <Step title="Crie a chave nova">
    Em **Configurações → Chaves de API**, crie uma chave nova. A antiga continua valendo.
  </Step>

  <Step title="Troque nos seus sistemas">
    Atualize o segredo em todos os lugares que usam a chave antiga e confira que as chamadas
    seguem respondendo `200`.
  </Step>

  <Step title="Revogue a antiga">
    No menu ⋮ da chave antiga, escolha **Revogar**. A revogação vale na requisição seguinte: a
    partir dela, a chave antiga recebe `401`.
  </Step>
</Steps>

Revogue na hora qualquer chave que possa ter vazado: publicada num repositório, enviada por chat
ou por HTTP.

## Quando a chave é recusada

Chave ausente, malformada, inexistente, revogada ou expirada recebe sempre o mesmo `401`
`invalid_api_key`, com a mesma mensagem. A resposta não diz qual foi o caso.

A chave é conferida **antes** dos parâmetros. Uma requisição com chave errada e parâmetro inválido
(por exemplo, `limit=500`) recebe `401`, não `400`.

Não repita um `401` em laço: 30 respostas `401` para o mesmo IP em 60 segundos bloqueiam o IP com
`429`. Veja [Limites de requisição](/concepts/rate-limits).

## Somente HTTPS

A API só aceita `https://`. Uma requisição em HTTP recebe `400` com corpo em texto puro
(`Use HTTPS: a API pública da Zouti não aceita HTTP.`), sem redirecionamento.

Se uma chave já foi enviada por HTTP, ela trafegou sem criptografia: revogue-a e crie outra.

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.zouti.com.br/v1/orders?limit=1" \
    -H "Authorization: Bearer $ZOUTI_API_KEY"
  ```

  ```javascript Node.js theme={null}
  // Node.js 18+ (fetch nativo). A chave vem do ambiente, nunca do código.
  const API_KEY = process.env.ZOUTI_API_KEY;
  if (!API_KEY) {
    console.error('Defina ZOUTI_API_KEY com a chave criada em Configurações → Chaves de API.');
    process.exit(1);
  }

  const response = await fetch('https://api.zouti.com.br/v1/orders?limit=1', {
    headers: { Authorization: `Bearer ${API_KEY.trim()}` },
  });

  if (response.status === 401) {
    console.error(`Chave recusada (Request-Id ${response.headers.get('Request-Id')}).`);
    console.error('Confira se foi copiada inteira, sem espaços, e se não foi revogada nem expirou.');
    process.exit(1);
  }

  const body = await response.json();
  console.log(`HTTP ${response.status}: chave aceita; ${body.data.length} pedido(s) na página.`);
  ```

  ```python Python theme={null}
  # Python 3 com requests. A chave vem do ambiente, nunca do código.
  import os
  import sys

  import requests

  api_key = os.environ.get("ZOUTI_API_KEY", "").strip()
  if not api_key:
      sys.exit("Defina ZOUTI_API_KEY com a chave criada em Configurações → Chaves de API.")

  response = requests.get(
      "https://api.zouti.com.br/v1/orders",
      params={"limit": 1},
      headers={"Authorization": f"Bearer {api_key}"},
      timeout=30,
  )

  if response.status_code == 401:
      sys.exit(
          f"Chave recusada (Request-Id {response.headers.get('Request-Id')}). "
          "Confira se foi copiada inteira, sem espaços, e se não foi revogada nem expirou."
      )

  body = response.json()
  print(f"HTTP {response.status_code}: chave aceita; {len(body['data'])} pedido(s) na página.")
  ```

  ```php PHP theme={null}
  <?php
  // PHP 7.4+ com a extensão curl. A chave vem do ambiente, nunca do código.
  $apiKey = trim((string) getenv('ZOUTI_API_KEY'));
  if ($apiKey === '') {
      fwrite(STDERR, "Defina ZOUTI_API_KEY com a chave criada em Configurações → Chaves de API.\n");
      exit(1);
  }

  $ch = curl_init('https://api.zouti.com.br/v1/orders?limit=1');
  curl_setopt_array($ch, [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_TIMEOUT => 30,
      CURLOPT_HTTPHEADER => ["Authorization: Bearer {$apiKey}"],
  ]);
  $raw = curl_exec($ch);
  if ($raw === false) {
      fwrite(STDERR, curl_error($ch) . PHP_EOL);
      exit(1);
  }
  $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);

  if ($status === 401) {
      fwrite(STDERR, "Chave recusada. Confira se foi copiada inteira, sem espaços, e se não foi revogada nem expirou.\n");
      exit(1);
  }

  $body = json_decode($raw, true);
  printf("HTTP %d: chave aceita; %d pedido(s) na página.\n", $status, count($body['data']));
  ```
</RequestExample>

<ResponseExample>
  ```json 401 theme={null}
  {
    "error": {
      "type": "authentication_error",
      "code": "invalid_api_key",
      "message": "Chave de API inválida.",
      "request_id": "req_8f2kq1x7c3m9v4b6n0zd5a"
    }
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.