Três endpoints, um header de autenticação, um corpo JSON. Uma API de encurtador de URL é uma das integrações mais simples em qualquer backlog, e o quickstart permite-lhe ter um link curto funcional em poucos minutos. O que o quickstart omite é tudo o que acontece quando a integração opera em volume: o limitador de taxa a rejeitar pedidos, um 503 transitório a meio de um lote, uma fila de trabalhos que entrega a mesma mensagem duas vezes. Erre nesses pontos e obterá links duplicados, trabalho perdido e uma tempestade de 429 que torna tudo ainda pior.
Este artigo é o complemento de endurecimento para produção do quickstart de API. Aborda os três mecanismos que separam uma demo de uma integração fiável: limites de taxa e como controlar o ritmo contra eles, quais os erros a retentar e como fazer backoff, e chaves de idempotência que impedem uma retentativa de criar um segundo link. Os exemplos usam a API do Elido, mas os padrões são os mesmos em qualquer API de encurtador bem construída. Se trata os links curtos como infraestrutura gerenciada por código, o argumento mais alargado está em links curtos como Terraform.
Limites de Taxa: um Token Bucket e Três Headers
O Elido mede a API com um token bucket, com âmbito por workspace. As taxas sustentadas publicadas são 10 pedidos por segundo no Free, 100 no Pro, 500 no Business, e um teto negociado no Enterprise. O Pro tem uma capacidade de burst de 200, o que significa que um bucket cheio permite disparar 200 pedidos de uma só vez antes de a taxa estabilizar nos 100 por segundo sustentados. A maioria dos trabalhos de criação de links cabe no burst e nunca sente o limite.
Não precisa de adivinhar onde está. Cada resposta inclui três headers:
X-RateLimit-Limit- o teto atual por segundo.X-RateLimit-Remaining- tokens restantes na janela atual.X-RateLimit-Reset- o timestamp Unix quando o bucket se reabastece.
Um cliente bem comportado lê X-RateLimit-Remaining e abranda antes de atingir zero, em vez de colidir com uma barreira de 429 e reagir após o fato. O controlo de ritmo proativo mantém o débito fluido; o retrying reativo após cada rejeição desperdiça viagens de ida e volta e, se todos os clientes retentam ao mesmo instante, cria uma manada trovoada.
Quando genuinamente precisa de criar milhares de links, não itere o endpoint de criação individual. POST /v1/links/bulk aceita até 1000 links num único pedido e conta como uma única unidade contra o limite de taxa. Uma chamada de bulk move mil links pelo custo de um token; mil chamadas individuais consomem mil tokens e a maior parte do seu burst. O endpoint de bulk é a forma como a importação do Google Sheets move links de uma campanha inteira sem acionar o limitador.
Um 429 Too Many Requests - o status que o RFC 6585 reserva precisamente para isto - é devolvido com um valor retry_after que indica quantos segundos esperar. Respeite-o. Esse número é o limitador a informá-lo exatamente quando um token estará disponível, o que é melhor do que qualquer estimativa que o seu backoff produziria.
Retentativas: Quais Códigos e Como Fazer Backoff
Nem todos os erros valem a pena retentar, e retentar o errado é como uma falha pequena se torna uma interrupção. Divida as respostas em dois grupos.
Retente estes, porque são transitórios: 429 (foi demasiado rápido), e 500, 502, 503, 504 (uma falha do lado do servidor ou do gateway que pode resolver-se por si). Não retente estes, porque o mesmo pedido vai falhar de forma idêntica: 400 (o payload é inválido), 401 (o token está ausente ou errado), 403 (o token não tem o scope), 404 (o recurso não existe ou não é seu), e 409 (conflito de slug ou edição com versão obsoleta). O primeiro grupo é "aguarde e tente novamente." O segundo é "corrija o código ou o input." Retentar um 400 em ciclo fechado transforma um bug num ataque de negação de serviço contra si próprio.
Para os códigos retentáveis, o algoritmo que importa é o backoff exponencial com jitter. O backoff exponencial simples - duplicar a espera a cada tentativa - ainda sincroniza clientes, porque todos os que falharam no mesmo momento também retentam nos mesmos momentos. Adicionar aleatoriedade dispersa-os. O artigo da AWS sobre exponential backoff and jitter é a referência canónica e mostra porque a versão com jitter reduz dramaticamente a contenção. Uma versão compacta em TypeScript:
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
async function withRetry<T>(
call: () => Promise<Response>,
max = 5,
): Promise<Response> {
let attempt = 0;
while (true) {
const res = await call();
if (res.ok || !RETRYABLE.has(res.status) || attempt >= max) return res;
// Honor server guidance first; otherwise back off exponentially with full jitter.
const retryAfter = Number(res.headers.get("retry-after"));
const base =
Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: Math.min(1000 * 2 ** attempt, 20_000);
const wait = Math.random() * base; // full jitter
await new Promise((r) => setTimeout(r, wait));
attempt++;
}
}
Três aspetos tornam isto seguro em vez de perigoso. Limita as tentativas, para que uma falha persistente falhe de forma clara em vez de girar indefinidamente. Respeita Retry-After quando o servidor o envia, recorrendo ao backoff calculado apenas quando não o faz. E aplica jitter, para que um conjunto de workers a recuperar do mesmo problema não se precipite em uníssono. Os SDKs oficiais implementam esta mesma política de raiz - @elido/sdk, elido-python e o cliente Go retentam exatamente os cinco códigos transitórios com backoff jitterizado - o que é a principal razão para usar um SDK em vez de um cliente HTTP feito à mão.
Há uma regra que liga as retentativas à seção seguinte: uma retentativa de criação só é segura se a criação for idempotente. Caso contrário, cada retentativa arrisca um segundo link.
Idempotência: Como Não Criar Links Duplicados
A falha clássica tem este aspeto. O seu worker cria um link curto, o link é criado, mas o 200 nunca chega de volta - a ligação cai na viagem de retorno. O worker vê um timeout, assume falha e retenta. Agora tem dois links para uma campanha. Em escala, o dashboard enche-se de /foo, /foo-1, /foo-2, e os duplicados distorcem todos os relatórios a jusante.
As chaves de idempotência fecham essa lacuna. Envie um header Idempotency-Key num pedido de mutação - qualquer string até 255 caracteres - e o servidor guarda a resposta associada a ela. Apresente a mesma chave novamente e recebe a resposta original de volta, código de status e corpo, sem a operação ser executada duas vezes. O padrão é o mesmo que a Stripe documenta para pedidos idempotentes, e é a forma padrão de tornar uma rede não fiável segura para escritas.
O detalhe que decide o sucesso ou falha é a origem da chave. Não gere uma chave aleatória por tentativa - isso anula o propósito, porque cada retentativa parece então uma operação nova. Derive-a de um identificador de negócio estável para que a mesma ação lógica produza sempre a mesma chave:
const link = await elido.links.create(
{ destinationUrl: order.landingUrl },
{ idempotencyKey: `order-${order.id}-link` },
);
Agora uma retentativa do mesmo trabalho carrega order-12345-link novamente, encontra a resposta armazenada e devolve o link que já existe. Exatamente um link por encomenda, independentemente de quantas vezes a fila reentrega. É isto que permite combinar o ciclo de backoff acima com criações de forma segura: a retentativa e a chave de idempotência são duas metades da mesma garantia.
Dois limites a ter em conta. A chave tem âmbito por workspace: a mesma chave em dois workspaces cria dois links, o que é correto para uma API multi-tenant mas surpreende equipes que assumem que as chaves são globais. E a cache não é permanente - no Elido dura 24 horas com âmbito em (workspace, key). Uma retentativa dentro da janela desduplicica; uma retentativa três dias depois, de um trabalho bloqueado que finalmente processou, criará um link novo. Para lotes de vários dias, não confie apenas na chave. Persista o ID do link devolvido pelo primeiro sucesso e consulte-o antes de reeditar a criação. O IETF tem estado a normalizar este header no rascunho Idempotency-Key, e a ressalva da janela de 24 horas está também mencionada lá.
Se está implementando uma integração de API hoje e quer que sobreviva às suas próprias retentativas, comece num workspace gratuito, gere um token de conta de serviço e coloque uma chave de idempotência na sua primeira criação em vez de a acrescentar depois de os duplicados aparecerem.
Juntar Tudo
Uma chamada de criação de qualidade para produção é os três mecanismos empilhados. Controle o ritmo contra os headers de limite de taxa para raramente atingir 429. Envolva a chamada em backoff jitterizado que retenta apenas os códigos transitórios e respeita Retry-After. Carregue uma chave de idempotência derivada de um ID de negócio para que a retentativa seja segura. Com o SDK oficial, os primeiros dois vêm incluídos e fornece apenas a chave:
import { Elido, ElidoRateLimitError } from "@elido/sdk";
const elido = new Elido({ token: process.env.ELIDO_TOKEN! });
export async function shortenForOrder(order: Order) {
try {
return await elido.links.create(
{ destinationUrl: order.landingUrl, tags: [`order:${order.id}`] },
{ idempotencyKey: `order-${order.id}-link` },
);
} catch (err) {
if (err instanceof ElidoRateLimitError) {
// SDK already retried with backoff; we are still limited. Defer the job.
throw new RetryableJobError(err.retryAfter);
}
throw err; // non-retryable: surface it
}
}
Nada disto é exótico. É a mesma disciplina que qualquer API com muitas escritas merece, aplicada a links. A recompensa é uma integração que se comporta corretamente sob carga em vez de corromper silenciosamente o seu inventário de links. Para o lado de leitura da mesma API - extrair dados de cliques sem sobrecarregar o limitador - os compromissos estão em webhooks versus polling para rastreamento de cliques, e a superfície completa de endpoints está na página de API e SDKs e na visão geral de soluções para programadores.
Relacionado no Blog
- API de encurtador de URL: um quickstart de 30 minutos em cinco linguagens
- Links curtos como Terraform: gerenciar links como código
- Webhooks versus polling para rastreamento de cliques
- Importar campanhas em massa do Google Sheets
- Ligar a API ao Claude e ao Cursor via MCP
- API gratuita de encurtamento de URL: a estrutura dos pedidos, autenticação e limites
Perguntas frequentes
Quais são os limites de taxa numa API de encurtador de URL?
No Elido, os limites publicados são 10 pedidos por segundo no Free, 100 no Pro com um burst de 200, 500 no Business, e um limite negociado no Enterprise, todos com âmbito por workspace. Cada resposta inclui os headers X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset para que um cliente possa controlar o ritmo antes de receber um 429. As criações em massa contam como uma única unidade contra o limite, por isso o endpoint de bulk é a ferramenta certa para trabalhos de grande volume.
Quais os erros de API que devo retentar?
Retente apenas falhas transitórias: 429 (limite de taxa atingido), 500, 502, 503 e 504. Use backoff exponencial com jitter e um limite máximo de retentativas. Nunca retente 400, 401, 403, 404 ou 409 - são falhas de validação, problemas de autenticação ou conflitos, e o mesmo pedido vai falhar novamente. Combine as retentativas com uma chave de idempotência para que uma criação reiterada não produza um link duplicado.
O que é uma chave de idempotência e quando preciso de uma?
Uma chave de idempotência é uma string opaca que envia num pedido de mutação para que o servidor possa reconhecer uma retentativa e devolver o resultado original em vez de agir duas vezes. Precisa de uma sempre que uma criação ou atualização pode ser retentada - o que é sempre, porque as redes falham e as filas de trabalhos entregam pelo menos uma vez. Derive a chave de um identificador de negócio estável, como um ID de encomenda, para que a mesma operação lógica use sempre a mesma chave.
Como evito criar links curtos duplicados?
Envie uma chave de idempotência derivada de um identificador de negócio estável em cada criação. Se a chamada for retentada, o servidor devolve o link originalmente criado em vez de gerar um segundo. Para trabalhos que podem ser retentados dias depois - além da janela de cache de idempotência - guarde também o ID do link devolvido pelo primeiro sucesso e consulte-o antes de reeditar a criação.
Quanto tempo dura uma chave de idempotência?
No Elido, a cache de idempotência tem uma duração de 24 horas, com âmbito no workspace mais a chave. Uma retentativa dentro dessa janela devolve a resposta armazenada; uma retentativa após esse período é tratada como um pedido novo e criará um novo recurso. Para trabalhos em lote de vários dias, persista o ID do link resultante no primeiro sucesso em vez de depender apenas da chave.
Experimente Elido
Cole uma URL, obtenha um link curto
Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.
Grátis, sem necessidade de registo · 2 por dia