Skip to content
Idioma: Português

API para programadores

Rate limits: todos os limites e cabeçalhos

Atualizado a 1 de novembro de 2026 6 min de leitura

Quantos pedidos por minuto a API do LinkHarbor permite, que tamanho pode ter um pedido, como ler os cabeçalhos e como tratar corretamente um 429.

Para manter a API rápida para todos, o LinkHarbor limita o número de pedidos por minuto. Os limites não dependem do seu plano – não existe uma quota mensal de chamadas à API. Este artigo lista todos os limites e mostra como o seu código os pode tratar de forma limpa.

Como são contados os pedidos

  • Cada pedido cai exatamente num bucket, por exemplo user para pedidos autenticados ou token para a troca de token
  • A contagem é feita por minuto completo (UTC); o contador volta a zero em cada novo minuto
  • Consoante o bucket, a API conta por espaço de trabalho, por pessoa, por ligação ou por endereço IP
  • Os pedidos que já falham no token, no scope ou no esquema (401, 403 insufficient_scope, 400, 422 validation_failed da verificação do esquema) não contam; erros posteriores, como 403 feature_not_available, contam

Todos os limites

Bucket (X-RateLimit-Bucket)LimiteContado porAplica-se a
user600 por minutoEspaço de trabalho para tokens de chaves de API (todas as chaves e ferramentas de IA do espaço de trabalho em conjunto); pessoa para sessões iniciadas no painelTodos os pedidos autenticados a /v1 que não têm bucket próprio
token30 por minutoEndereço IPPOST /v1/token
public120 por minutoEndereço IPPedidos à API sem autenticação, como GET /v1/plans e GET /v1/pages/available
callback120 por minutoEndereço IPPOST /v1/callbacks/sale
internal120 por minutoEndereço IPURL de ingestão da integração «Custom (API)» (POST /v1/ingest/{id})
mcp120 por minutoLigação de IA (token de acesso)Servidor MCP em /mcp
oauth300 por minutoEndereço IPInício de sessão OAuth e descoberta para assistentes de IA
auth30 por minutoEndereço IPInício de sessão, registo, reposição da palavra-passe (painel e app)
refresh120 por minutoEndereço IPProlongar uma sessão do painel
discover60 por minutoPessoa, endereço IP sem sessão iniciadaA secção Descobrir da app
subs_read120 por minutoPessoa, endereço IP sem sessão iniciadaLer as páginas que segue (app)
subs_write20 por minutoPessoa, endereço IP sem sessão iniciadaAlterar as páginas que segue (app)

Um orçamento por espaço de trabalho

Todos os tokens de chaves de API do mesmo espaço de trabalho partilham os 600 pedidos por minuto – independentemente de quantas chaves criar. As ferramentas dos assistentes de IA ligados também contam aqui, porque chamam a API internamente. Por isso, mais chaves não aumentam o limite. Se distribuir muita carga por vários programas, planeie em função do orçamento partilhado.

Os cabeçalhos

X-RateLimit-Limit
O limite do bucket por minuto, por exemplo 600.
X-RateLimit-Remaining
Quantos pedidos restam no minuto atual.
X-RateLimit-Bucket
O bucket em que o pedido caiu, por exemplo user.
Retry-After
Só com 429 rate_limited: segundos até ao início do minuto seguinte. Com api_key_locked, o tempo de espera está em details.retry_after_sec.

Quando o limite é atingido

Quando o limite é atingido, a API responde com HTTP 429 e este corpo. O texto de message está no idioma da conta (ver Formato de erro e códigos de erro), aqui em inglês; o código rate_limited mantém-se:

Resposta com 429
HTTP/1.1 429 Too Many Requests
Retry-After: 37
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Bucket: user

{ "error": "rate_limited", "message": "Too many requests. Please try again in a moment.", "retry_after_sec": 37 }
  1. Leia Retry-After ou retry_after_sec
  2. Espere pelo menos esses segundos, mais um pouco de aleatoriedade, para que nem todos os processos recomecem no mesmo momento
  3. Repita o pedido no máximo algumas vezes
  4. Se continuar a receber 429, distribua o trabalho por mais tempo
Node.js: guardar o token em cache e tratar o 429
const BASE = 'https://dock.at-harbor.com';
let cached = null; // { token, expiresAt }

async function getToken() {
  if (cached && Date.now() < cached.expiresAt - 60_000) return cached.token;
  const res = await fetch(BASE + '/v1/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      key_id: process.env.LH_KEY_ID,
      key_secret: process.env.LH_KEY_SECRET,
    }),
  });
  if (!res.ok) throw new Error('Falha na troca do token: HTTP ' + res.status);
  const data = await res.json();
  cached = { token: data.token, expiresAt: Date.now() + data.expires_in * 1000 };
  return cached.token;
}

async function lh(method, path, body, attempt = 0) {
  const headers = { Authorization: 'Bearer ' + (await getToken()) };
  if (body !== undefined) headers['Content-Type'] = 'application/json';

  const res = await fetch(BASE + path, {
    method,
    headers,
    body: body === undefined ? undefined : JSON.stringify(body),
  });

  if (res.status === 429 && attempt < 3) {
    const wait = Number(res.headers.get('Retry-After') ?? 5);
    await new Promise((r) => setTimeout(r, (wait + Math.random() * 2) * 1000));
    return lh(method, path, body, attempt + 1);
  }
  if (res.status === 401 && attempt === 0) {
    cached = null; // token expirado – tentar mais uma vez com um token novo
    return lh(method, path, body, attempt + 1);
  }
  const data = await res.json().catch(() => null);
  if (!res.ok) throw new Error((data && data.error) + ' (HTTP ' + res.status + ')');
  return data;
}

// Exemplo: const { items } = await lh('GET', '/v1/pages');

Dicas para grandes volumes de dados

  • Guarde o token em cache e renove-o só pouco antes de expirar, ao fim de 15 minutos
  • Acompanhe X-RateLimit-Remaining e abrande quando o valor ficar baixo
  • Envie os pedidos um após outro, em vez de usar dezenas de ligações paralelas
  • Carregue as listas uma vez e filtre-as localmente, em vez de consultar cada página individualmente
  • Distribua as sincronizações grandes por vários minutos
  • Repita os erros 5xx com pausas crescentes, mas não os erros 4xx

Outros limites

O quêLimiteResposta
Inícios de sessão falhadosBloqueio após 5, 10 e 20 tentativas falhadas por endereço de e-mail e IP: 60 segundos, 5 minutos, 30 minutos429 account_locked
Submissões de formulários10 por hora e endereço IP, em todos os formulários429 form_rate_limited

As tentativas falhadas na troca de token bloqueiam temporariamente a chave e o IP, veja Chaves de API e tokens de acesso. As notificações push só são enviadas no painel; os respetivos limites estão explicados em Seguidores e notificações push.

Os limites de conteúdo do seu plano – páginas, links, blocos, links curtos, etc. – não são rate limits, mas sim limites fixos. Estão listados em Comparação de planos.

Tamanho do pedido

Cada corpo é medido antes de a API o ler. O tamanho permitido depende do endpoint:

EndpointsCorpo máximo
Início de sessão, registo e as restantes chamadas sem autenticação em /v1/auth, POST /v1/token, POST /v1/oauth/exchange, os endpoints OAuth para assistentes de IA em /oauth e o respetivo consentimento, POST /v1/ingest/{id}, o checkout do bloco «Apoiar», as chamadas de subscrição da app (seguir, coleções, dispositivos push), a mudança de espaço de trabalho, POST /v1/auth/logout-all, a eliminação de uma conta, a configuração de dois fatores, a aceitação de um convite, a ativação do programa de recomendação e o passo de regresso ao ligar uma integração64 KB
Todos os outros endpoints JSON, incluindo o envio de um formulário numa página1 MB
POST /v1/webhooks/{id}/verify-signature e o servidor MCP em /mcp2 MB
Carregamentos de ficheiros (POST /v1/assets e POST /v1/pages/{id}/uploads, multipart/form-data)11 MB para o pedido completo, o próprio ficheiro no máximo 10 MB

Se o corpo for maior, a API responde com 413 request_too_large; details.max_bytes e details.max_kb indicam o limite. Um ficheiro demasiado grande num carregamento leva a 413 payload_too_large. Os endpoints sem corpo, como as chamadas DELETE, não aceitam corpo ou aceitam apenas {}.

Resposta com 413
HTTP/1.1 413 Payload Too Large

{ "error": "request_too_large", "message": "…", "details": { "max_bytes": 65536, "max_kb": 64 }, "request_id": "…" }

Também há limites dentro do corpo: cada texto tem um comprimento máximo, cada lista um número máximo de entradas, e os campos desconhecidos são recusados. Os valores estão indicados por endpoint na referência da API. Uma violação leva a 422 validation_failed, e details indica o campo, a regra e o limite. O caminho e a query string de um pedido podem ter, em conjunto, no máximo 16 KB.

Não encontrou o que procura?

Diga-nos de que precisa e a nossa equipa de suporte ajuda-o pessoalmente.

Contactar o suporte