8 min de leituraIntegrações

Integração do Linear com o encurtador de URL - criação automática de issues em alertas de limite

Conecte a detecção de links quebrados e os picos de limite de cliques da Elido a uma equipe no Linear. Configuração, filtro de equipe, roteamento de labels, modos de falha reais.

Marius Voß
DevRel · edge infra
Pipeline de detecção até o ticket mostrando a integração do Linear com o encurtador de URL criando uma issue a partir de um evento de link quebrado

O Linear entrou em Live no catálogo de integrações da Elido em 2026-05-22. O primeiro evento que lançamos foi o broken_link_hook - quando nosso scanner encontra um link curto morto, ele cria uma issue no Linear na equipe que você escolheu no momento do Connect, com métricas de clique no corpo e labels roteadas por tag. Este post é o passo a passo do engenheiro: como funciona a autenticação, como é o payload JSON, e como estendemos o mesmo pipe para os picos de limite de cliques para que o plantão receba um ticket em vez de um alerta às 3 da manhã.

Se você mantém centenas ou milhares de links curtos em produção, você já conhece esse modo de falha. O marketing troca o destino de uma campanha, a nova URL retorna 404, e ninguém percebe até um cliente tirar um print de um link morto no Bluesky. O Linear é onde sua equipe já trata os bugs, então é lá que colocamos o ticket.

Conectando o Linear via Personal API Key

A integração com o Linear usa uma Personal API Key, não OAuth. Tomamos essa decisão por três razões: as API Keys são vinculadas ao workspace, sobrevivem melhor à troca de administradores do que tokens OAuth presos a um único usuário, e a documentação API: Authentication do Linear recomenda explicitamente esse uso para jobs server-to-server.

Gere a chave no Linear: Settings, API, Personal API keys, Create key. Dê a ela o nome elido-integration para poder revogá-la depois sem ficar adivinhando qual é. Copie a chave (ela começa com lin_api_) e cole no card de integração do Linear no painel da Elido.

O que acontece a seguir: fazemos uma query viewer para validar a chave, depois uma query teams para preencher o seletor de equipe. Você seleciona uma equipe padrão. Essa escolha grava uma linha em integration_configs no Postgres, incluindo o ID de equipe atribuído pelo Linear. Se você tiver várias equipes, pode adicionar roteamento por tag na mesma tela - mais sobre isso abaixo.

POST /v1/workspaces/:id/integrations/linear/connect
{
  "api_key": "lin_api_<redacted>",
  "default_team_id": "TEAM_a1b2c3",
  "default_priority": 2,
  "labels": ["short-link", "auto-filed"]
}

Nos bastidores, o serviço api-core armazena a chave criptografada em repouso (encrypted at rest) usando o esquema de envelope-encryption da ADR-0036. A chave descriptografada só existe em memória durante a chamada GraphQL propriamente dita. Nunca registramos o valor bruto em log, e a UI de logs de integração mostra apenas os últimos 4 caracteres.

Um detalhe importante: as Personal API Keys do Linear ficam vinculadas ao usuário que as criou. Se esse usuário sai da sua empresa e você faz o offboarding do assento (seat) dele no Linear, a chave morre junto. A boa prática é criar no Linear um usuário do tipo service (nós usamos [email protected]) e gerar a chave a partir dessa conta.

Diagrama do url-scanner detectando um destino de redirecionamento quebrado e disparando um evento broken_link_hook para a Issues API do Linear

Nosso serviço url-scanner faz uma varredura semanal de todos os links curtos ativos no seu workspace. Para cada link, ele faz um HTTP HEAD no destino, depois um GET se o HEAD não for suportado, e então valida a cadeia TLS. Quatro condições disparam o estado de link quebrado:

  1. HTTP 4xx ou 5xx em duas verificações consecutivas (verificamos duas vezes para absorver 500 transitórios)
  2. TLS expirado ou self-signed onde estava válido na semana anterior
  3. DNS NXDOMAIN - o host de destino não resolve mais
  4. Correspondência de fingerprint de domínio estacionado - o destino resolve, mas o corpo da resposta corresponde a um template conhecido de squatter (mantemos um pequeno conjunto de fingerprints)

Quando qualquer uma dessas quatro condições dispara, o scanner publica um evento link.broken no Redpanda. O webhook-dispatcher o consome, verifica suas integrações ativas, e para o Linear materializa o payload abaixo.

Aqui está um payload real de broken_link_hook, capturado do nosso ambiente de staging (alguns campos foram omitidos):

{
  "event": "link.broken",
  "link_id": "01J9V7QXMZ8K2Y3N4P5R6T7W8Z",
  "short_url": "https://s.elido.me/spring-launch",
  "destination_url": "https://oldcampaign.example.com/landing",
  "failure_type": "http_5xx",
  "failure_detail": "502 Bad Gateway, 2 consecutive probes",
  "last_working_at": "2026-05-28T14:22:00Z",
  "detected_at": "2026-06-04T03:11:42Z",
  "clicks_last_7d": 2841,
  "clicks_last_24h": 412,
  "top_referrers": [
    { "host": "linkedin.com", "clicks": 1203 },
    { "host": "twitter.com", "clicks": 488 },
    { "host": "direct", "clicks": 612 }
  ],
  "tags": ["campaign-spring-2026", "paid"],
  "owner_email": "[email protected]"
}

O adapter do Linear em services/api-core/internal/integrations/linear/broken_link_hook.go pega esse payload e constrói uma mutation GraphQL contra a Issues API do Linear. O título da issue segue um padrão fixo para que o plantão consiga dar grep:

[Elido] Broken link: /spring-launch (502 Bad Gateway)

O corpo é Markdown estruturado em cinco seções: detalhes do link, timestamp da última vez que funcionou, delta de cliques em relação à linha de base de 7 dias, os três principais referrers, e um bloco de correção sugerida. O bloco de correção sugerida olha para failure_type e escolhe uma sugestão de template - para http_5xx, «Verifique se o destino está com rate limit ou em deploy»; para parked_domain, «O domínio pode ter expirado ou sido tomado por squatting, arquive este link»; e assim por diante.

As labels são atribuídas a partir de duas fontes: seu conjunto padrão de labels (configurado no Connect) e labels dinâmicas derivadas da lista de tags. Se uma tag corresponde a paid ou organic, adicionamos como label para que os PMs possam filtrar suas visualizações no Linear.

Dedup, rate limits e a dead-letter queue

Fazemos dedup de eventos broken_link_hook por host de destino durante 24 horas. Se oldcampaign.example.com morrer e 800 links curtos apontarem para ele, você recebe um único ticket no Linear com todas as 800 URLs curtas listadas no corpo, não 800 tickets separados. Essa foi uma lição difícil da beta inicial - o primeiro cliente que bateu em um domínio morto ficou soterrado de tickets.

O endpoint GraphQL do Linear tem um rate limit global por workspace. Nosso webhook-dispatcher acompanha o header Retry-After e usa backoff exponencial com jitter completo, até cinco tentativas. Depois da quinta, o evento cai em uma dead-letter queue. Você pode ver as entradas da DLQ em Settings, Integrations, Linear, Failed events, e reprocessar qualquer uma delas com um clique. A DLQ também é exposta pela funcionalidade de webhooks para reprocessamento programático.

Limites de clique e gatilhos personalizados

Mockup do corpo de uma issue no Linear criada pela Elido, mostrando o padrão de título, as seções do corpo e o roteamento de labels

O mesmo adapter do Linear consome eventos click_threshold_hook. Você define limites por link ou por campanha no painel da Elido, e criamos uma issue no Linear quando um link cruza uma faixa. Hoje são suportados dois tipos de faixa:

  • Spike (pico): os cliques na última hora excedem N vezes a linha de base horária dos últimos 7 dias (o N padrão é 3). Útil para capturar viralização ou, menos felizmente, tráfego de bots.
  • Cliff (queda): os cliques na última hora caem abaixo de 10% da linha de base. Útil para capturar campanhas mortas - se um anúncio pago foi pausado lá na origem, você vê um ticket no Linear antes do standup de marketing.

Aqui está um payload de click_threshold_hook:

{
  "event": "link.click_threshold",
  "link_id": "01J9V7QXMZ8K2Y3N4P5R6T7W8Z",
  "short_url": "https://s.elido.me/spring-launch",
  "band": "spike",
  "current_hour_clicks": 8421,
  "baseline_hourly_clicks": 612,
  "multiplier": 13.76,
  "top_referrers": [
    { "host": "news.ycombinator.com", "clicks": 6203 },
    { "host": "direct", "clicks": 1488 }
  ],
  "tags": ["campaign-spring-2026"],
  "triggered_at": "2026-06-04T11:14:00Z"
}

Para um spike, o bloco de correção sugerida diz: «Verifique se este é tráfego orgânico, não uma campanha de referrer-spoofing. Confira a distribuição de referrers acima». Para um cliff: «Confirme se a campanha ainda está ativa na origem. Se foi pausada, arquive este link».

Roteamento por tag entre várias equipes

O seletor de equipe padrão funciona bem para um workspace de 20 pessoas. Para organizações maiores, você quer que um ticket no Linear sobre um link de marketing vá para a equipe Marketing, e um ticket sobre um link de docs vá para a equipe Documentation. É isso que o roteamento por tag resolve.

As regras de roteamento vivem em integration_configs.routing_json e são avaliadas de cima para baixo. Uma regra se parece com isto:

[
  {
    "tag_glob": "campaign-*",
    "team_id": "TEAM_growth",
    "labels": ["growth", "urgent"]
  },
  { "tag_glob": "docs-*", "team_id": "TEAM_docs", "labels": ["docs"] },
  {
    "tag_glob": "internal-*",
    "team_id": "TEAM_internal",
    "labels": ["internal"]
  },
  { "default": true, "team_id": "TEAM_a1b2c3" }
]

Vence a primeira regra cujo glob corresponde a pelo menos uma tag do link. Se nada corresponder, a regra padrão assume o evento. A sintaxe de glob é a mesma dos filtros de saved-view do Linear, então os PMs já a conhecem.

Você também pode rotear por failure_type. Algumas equipes querem que todas as falhas de TLS vão para a equipe de platform, já que costumam indicar configuração incorreta de certificado em um domínio customizado de tenant. Adicione uma regra com a chave failure_type: tls_expired e pronto.

Gatilhos personalizados via webhooks

Nem toda equipe quer criar tickets no Linear para cada tipo de evento que publicamos. O catálogo completo de eventos está documentado na página da funcionalidade de webhooks, mas as combinações mais comuns que as equipes configuram junto com o Linear são:

  • link.created para uma equipe no Linear em auditorias de novos links (raro, geralmente para equipes de compliance)
  • domain.takeover_detected para surpresas de TLS em domínios customizados
  • link.scan_complete para tickets de resumo semanal (uma issue por execução de varredura, listando todos os links sinalizados)

Se o evento que você quer não está no catálogo, você pode construir o seu próprio usando o destino genérico de webhook e nosso guia de observability. Ou simplesmente abra um feature request no nosso board público do Linear - meta, mas recursivo.

Preços e o que você recebe em cada plano

A integração com o Linear está incluída a partir do tier Pro. No Free, você pode conectar o Linear, mas só recebe o broken_link_hook (sem limite de cliques ou gatilhos personalizados). Veja a página de preços para a matriz completa. Se você é uma equipe maior pensando nisso por razões de compliance - digamos, o Artigo 32 do GDPR exige que você detecte vazamentos de dados vindos de redirecionamentos quebrados apontando para domínios de squatters - a página de soluções Enterprise cobre o que oferecemos em escala.

Relacionado no Blog

O catálogo de integrações completo lista 43 fornecedores em junho de 2026, com o Linear entre os 20 que estão Live. Se sua equipe usa o Jira em vez disso, esse adapter está em beta - mande um e-mail para nós e nós ativamos para você.

Perguntas frequentes

Como a Elido autentica com o Linear?

Usamos uma Personal API Key vinculada ao workspace, não OAuth. Você gera a chave no Linear em Settings, API, e depois cola no card de integração da Elido. A chave nunca sai do nosso vault e é ocultada dos logs. Se você a rotacionar, o próximo evento dispara um aviso de reautenticação em vez de falhar silenciosamente.

O que exatamente conta como link quebrado no evento broken_link_hook?

Nosso url-scanner varre cada link curto ativo semanalmente e sinaliza quatro condições: HTTP 4xx ou 5xx em duas verificações consecutivas, certificado TLS expirado ou não verificável, DNS NXDOMAIN, e fingerprints conhecidos de domínio estacionado (parked domain). Qualquer uma dessas quatro condições dispara uma única issue no Linear, deduplicada por host de destino durante 24 horas, para que um domínio morto não gere 800 tickets.

Posso enviar issues para equipes diferentes no Linear com base nas tags do link?

Sim. Na tela Connect você escolhe uma equipe padrão e depois adiciona regras de roteamento - por exemplo, tags que combinam com campaign-* vão para a equipe Growth, enquanto tags que combinam com docs-* vão para Engineering. As regras são avaliadas de cima para baixo, com um fallback padrão. O conjunto de regras vive no Postgres, então você pode auditar as mudanças pela trilha de administração (admin trail).

Isso funciona também para alertas de limite de cliques, não só para links quebrados?

Sim, desde a Fase 12. O mesmo adapter do Linear consome eventos click_threshold_hook junto com broken_link_hook. Você define limites por link ou por campanha no painel da Elido, e nós criamos uma issue no Linear quando um link cruza uma faixa - seja um pico (3x a linha de base em uma hora) ou uma queda (cair abaixo de 10% da linha de base).

O que acontece se o Linear aplicar rate limit na integração?

O endpoint GraphQL do Linear retorna um 429 com um header Retry-After. Nosso webhook-dispatcher respeita isso com backoff exponencial de até cinco tentativas, e então coloca o evento em uma dead-letter queue. Você pode reprocessar entradas da DLQ pela UI de logs de integração, ou via API GraphQL em /v1/integrations/linear/dlq. Ainda não vimos um 429 sustentado do Linear em produção.

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

Experimente o Elido

Encurtador de URL hospedado na UE: domínios personalizados, análises profundas e API aberta. Plano gratuito - sem cartão de crédito.

Tags
linear url shortener integration
linear broken link detection
linear automation
linear API integration
short link alerts linear

Continuar lendo