Pular para o conteúdo
ZapCar
Developersv1

Limites e idempotência

Rate limit por conta e por IP, cabeçalhos RateLimit-* e a Idempotency-Key que evita cobrança dupla.

Limite de requisições

A API aceita, por padrão, 120 requisições por minuto em produção e 60 com a chave de teste. A contagem é feita em janela de 60 segundos e em duas camadas: por IP de origem (antes da autenticação) e por conta e ambiente (depois dela). Os contadores de teste e de produção são separados: um laço contra o sandbox nunca gasta a cota da integração que está no ar.

Se a sua operação precisar de outro volume, fale com a equipe antes de subir a carga.

Cabeçalhos de limite

Toda resposta traz o estado do limite, para você se ajustar antes de ser barrado:

CabeçalhoConteúdo
RateLimit-LimitTeto da janela (ex.: 120).
RateLimit-RemainingQuantas requisições ainda cabem nesta janela.
RateLimit-ResetSegundos até a janela zerar.
Retry-AfterSó no 429: quantos segundos esperar. Respeite este valor em vez de escolher um intervalo por conta própria.
HTTPresposta 429
HTTP/1.1 429 Too Many Requests
Retry-After: 37
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 37

{
  "erro": "Limite de requisições excedido para esta conta. Tente novamente em instantes.",
  "codigo": "RATE_LIMITED",
  "retryable": true
}
Dica:
Um 429 não consome saldo e não cria consulta: é seguro repetir depois do Retry-After. O que não é seguro é repetir num laço apertado, que mantém a janela sempre cheia.
Atenção:
Polling de muitas consultas ao mesmo tempo é o gargalo mais comum. Com webhook, cada consulta gera uma chamada quando fica pronta, em vez de uma a cada 4 segundos enquanto processa. Ver Webhooks.

Idempotência: evite cobrança duplicada

O saldo é debitado no POST. Se a resposta se perder no caminho (timeout do seu cliente HTTP, processo reiniciado, deploy no meio da requisição), você não sabe se a consulta foi criada. Repetir o POST às cegas cria uma segunda consulta e um segundo débito.

O cabeçalho Idempotency-Key resolve isso: um identificador seu, único por operação. Se a mesma chave chegar de novo com o mesmo corpo, devolvemos a resposta da primeira, sem criar consulta nova e sem cobrar de novo.

cURLa mesma requisição, repetível com segurança
curl -X POST "https://api.zapcarconsulta.com.br/v1/consultas" \
  -H "Authorization: Bearer $ZAPCAR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-erp-984281" \
  -d '{"servico":"consulta","placa":"ABC1D23"}'
Dica:
Use como chave o identificador do pedido no seu sistema (número da OS, id do registro, id do job da fila). Se o seu processo cair e reprocessar o mesmo item, a chave volta idêntica e a proteção funciona. Chave aleatória gerada a cada tentativa não protege nada.

O que você recebe em cada caso

SituaçãoResposta
Primeira vez com a chave201: consulta criada e cobrada normalmente.
Mesma chave e mesmo corpo, primeira já concluída201 com a mesma resposta da primeira (mesmo id). Nada é cobrado de novo.
Mesma chave enquanto a primeira ainda está sendo criada409 IDEMPOTENCY_IN_PROGRESS, com retryable: true. Espere alguns segundos e repita com a mesma chave.
Mesma chave com corpo diferente422 IDEMPOTENCY_KEY_REUSED. Nada é criado: uma chave pertence a uma operação só.
Chave fora do formato400 IDEMPOTENCY_KEY_INVALIDA.
Informação:
Em POST /v1/fipe e POST /v1/fipe/tabela o replay devolve o mesmo 200 da primeira resposta.

Regras da Idempotency-Key

RegraComportamento
Onde valeNos endpoints que cobram: POST /v1/consultas, POST /v1/fipe e POST /v1/fipe/tabela.
FormatoDe 8 a 255 caracteres. Qualquer texto; recomendamos algo rastreável do seu lado.
EscopoPor conta. A chave de um cliente nunca colide com a de outro.
Validade30 dias. Depois disso, a mesma chave volta a ser tratada como nova (e cobra).
ConcorrênciaDuas requisições simultâneas com a mesma chave: uma executa e a outra recebe 409. Nunca as duas cobram.
Se a criação falharA chave é liberada (ex.: saldo insuficiente, validação). Reenviar com a mesma chave conta como tentativa nova.
Sem o cabeçalhoComportamento histórico, sem a proteção.
No sandboxO cabeçalho é aceito e ignorado: no ambiente de teste nada é cobrado.
Atenção:

Uma chave por tentativa, não por placa

A Idempotency-Key protege o retry de rede, não a nova tentativa de uma consulta que falhou. Se o status virou erro, a próxima tentativa é uma consulta nova e precisa de chave nova (pedido-984281-t2): reusar a anterior devolveria, em replay, a consulta que já falhou. Ver o guia de resiliência.

Proteção automática contra pedido duplicado

Mesmo sem o cabeçalho, um POST /v1/consultas do mesmo serviço para o mesmo identificador enquanto a consulta anterior ainda está em processamento devolve 200 com reaproveitada: true, valor_cobrado: 0 e o id da consulta existente. Isso cobre o duplo clique e o retry imediato.

JSONresposta 200: solicitação idêntica já em andamento
{
  "id": "6f1c2e2a-1b3d-4a9e-8f7c-2a1b3c4d5e6f",
  "servico": "consulta",
  "status": "processando",
  "valor_cobrado": 0,
  "saldo_restante": 465.01,
  "resultado_url": "/v1/consultas/6f1c2e2a-1b3d-4a9e-8f7c-2a1b3c4d5e6f",
  "reaproveitada": true,
  "mensagem": "Essa solicitação já está sendo processada. Você não precisa realizar uma nova."
}

O que essa proteção não cobre: a consulta anterior já terminou. Aí um POST novo cria e cobra outra consulta, como deve ser. Para o retry de rede, use a chave.