Voltar para artigos
Para desenvolvedores

API do Pingu Link: Como Integrar o Encurtador ao Seu Site ou Bot

11 min PinguLink

Uma chamada GET devolve o link curto em JSON. A chave exige nível 3. Parâmetros, formato da resposta, limite de chamadas e como tratar erro em produção.

Se você tem um bot, um site ou um sistema que precisa gerar links curtos automaticamente, a integração com o Pingu Link é uma única chamada HTTP. Sem SDK para instalar, sem autenticação em duas etapas, sem dependência para manter.

Antes de começar: a chave exige nível 3

A chave de API aparece sozinha na sua conta a partir do nível 3. Abaixo disso ela só é liberada por solicitação ao suporte.

Não é burocracia: a chave gera links na sua conta, e liberá-la para qualquer cadastro recém-criado seria um convite a abuso. Como se sobe de nível está em Sistema de Níveis do Pingu Link.

A chamada

Um GET com a sua chave e o endereço de destino:

GET https://pingulink.com/api?api=SUA_CHAVE&url=https://exemplo.com/pagina

A resposta vem em JSON:

{
  "status": "success",
  "message": "",
  "shortenedUrl": "https://pingulink.com/a3f9"
}

E, em caso de erro, no mesmo formato:

{
  "status": "error",
  "message": "Invalid API token",
  "shortenedUrl": ""
}

Repare que o erro também volta com HTTP 200. Quem trata só o código HTTP nunca vê a falha — o campo que decide é o status.

Os parâmetros

ParâmetroObrigatórioO que faz
apisimSua chave
urlsimO endereço de destino
aliasnãoEscolhe o final do link em vez de sortear
typenãoQuantidade de etapas, de 0 a 6 — sobrescreve a da chave
formatnãojson (padrão) ou text

Com format=text a resposta é só o endereço, sem JSON — e, em caso de erro, vem vazia. É prático para colar direto numa mensagem, e perigoso se você não tratar o vazio.

A chave e as etapas

A chave é gerada no painel e carrega a própria configuração de etapas. Isso é mais útil do que parece à primeira vista: você não precisa passar esse parâmetro em cada chamada, e pode separar contextos sem tocar no código.

  • Uma chave de 2 etapas para o bot que atende público novo.
  • Uma chave de 4 etapas para o canal principal.
  • Uma chave de 5 etapas para o conteúdo exclusivo.

Trocar a configuração vira uma mudança no painel, não um deploy. E quando você precisar de uma exceção pontual, o parâmetro type sobrescreve a chave só naquela chamada.

Segurança da chave

Trate a chave como senha, porque é uma: quem a tiver gera links na sua conta.

  • Ela fica no servidor. Nunca em JavaScript que roda no navegador do visitante, nunca em aplicativo distribuído.
  • Nunca em repositório. Use variável de ambiente. Chave commitada em repositório público é encontrada por robô em minutos.
  • Revogue ao suspeitar. Gerar uma nova e trocar leva menos tempo que investigar.

Tratando a resposta

Sempre confira o campo status antes de usar o shortenedUrl. Integração que assume sucesso quebra silenciosamente no dia em que a chave for revogada ou o destino for recusado — e quebra em produção, não no teste.

const r = await fetch(url).then(r => r.json());

if (r.status === 'success') {
  usar(r.shortenedUrl);
} else {
  registrar(r.message);
  usar(destinoOriginal);   // entrega o link original
}

O padrão acima é o que eu recomendaria para qualquer integração: em caso de falha, entregue o link original. Você perde a receita daquela visita e não perde o usuário. O contrário — não entregar nada — perde os dois.

Boas práticas que evitam dor de cabeça

Guarde o resultado

Não gere o mesmo link várias vezes. Chamar a API a cada exibição desperdiça requisição e polui a sua lista com centenas de links idênticos, o que destrói as estatísticas.

Guarde o par destino → link curto no seu banco e reutilize.

Respeite um intervalo mínimo

Rajadas de centenas de chamadas por segundo são tratadas como abuso. Se você precisa gerar muitos links de uma vez, espace as chamadas.

Tenha um tempo limite

Se a API não responder em poucos segundos, siga com o link original em vez de travar o seu fluxo. Um bot que congela esperando resposta é pior que um bot que entrega link não monetizado.

const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 4000);
fetch(url, { signal: ctrl.signal })

Registre as falhas

Guarde o motivo de cada erro. Sem log, o dia em que a integração parar vira investigação às cegas — e normalmente é algo simples, como chave revogada ou destino bloqueado.

Onde isso costuma ser usado

  • Bot de Telegram que entrega conteúdo. O caso mais comum: o bot gera o link na hora, a pessoa passa pelas etapas e recebe o que pediu.
  • Site com área de downloads. Cada arquivo tem seu link gerado dinamicamente.
  • Automação de publicação. O sistema publica em redes sociais já com o link monetizado.
  • Encurtador interno. Sua ferramenta usa o Pingu Link por baixo, sem o usuário perceber.

Se o seu caso é o do Telegram, talvez você nem precise programar: existe um gerador de bots pronto que faz isso por configuração, incluindo convite temporário e remoção automática.

Exemplos em três linguagens

A integração é a mesma em qualquer lugar: um GET e a leitura de dois campos.

PHP

function encurtar(string $destino): string {
    $url = 'https://pingulink.com/api?api=' . getenv('PGL_CHAVE')
         . '&url=' . urlencode($destino);

    $ctx = stream_context_create(['http' => ['timeout' => 4]]);
    $bruto = @file_get_contents($url, false, $ctx);
    $r = $bruto ? json_decode($bruto, true) : null;

    // em caso de falha, o link original -- nunca nada
    return (($r['status'] ?? '') === 'success') ? $r['shortenedUrl'] : $destino;
}

Python

import os, requests

def encurtar(destino):
    try:
        r = requests.get('https://pingulink.com/api', timeout=4, params={
            'api': os.environ['PGL_CHAVE'],
            'url': destino,
        }).json()
        return r['shortenedUrl'] if r.get('status') == 'success' else destino
    except Exception:
        return destino

Node

async function encurtar(destino) {
  const u = new URL('https://pingulink.com/api');
  u.searchParams.set('api', process.env.PGL_CHAVE);
  u.searchParams.set('url', destino);

  try {
    const r = await fetch(u, { signal: AbortSignal.timeout(4000) })
      .then(r => r.json());
    return r.status === 'success' ? r.shortenedUrl : destino;
  } catch {
    return destino;
  }
}

Repare no padrão comum aos três: toda falha devolve o destino original. É a decisão de projeto mais importante da integração — você perde a receita de uma visita e não perde o usuário.

Guardando o resultado

Chamar a API a cada exibição é o erro mais comum, e ele tem dois custos: desperdício de requisição e destruição das suas estatísticas, porque o mesmo destino vira centenas de links diferentes.

A correção é uma tabela de duas colunas:

CREATE TABLE links_curtos (
  destino  VARCHAR(500) NOT NULL,
  curto    VARCHAR(190) NOT NULL,
  criado   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (destino(190))
);

Antes de chamar a API, consulte. Depois de receber, grave. Duas linhas de código que evitam milhares de chamadas por mês.

Ambiente de teste sem sujar a conta

Durante o desenvolvimento você vai gerar dezenas de links de mentira, e eles ficam para sempre na sua lista atrapalhando a leitura.

Duas soluções, ambas simples:

  • Uma chave só para desenvolvimento. Você separa o que é teste do que é produção e pode revogá-la sem afetar nada.
  • Um interruptor no código. Em ambiente local, a função devolve o destino original sem chamar a API.
if (process.env.NODE_ENV !== 'production') return destino;

A segunda é a que eu recomendaria: além de manter a conta limpa, ela deixa o desenvolvimento mais rápido, porque não há requisição de rede em cada teste.

Checklist antes de colocar em produção

  • A chave está em variável de ambiente, não no código
  • Existe tempo limite na requisição
  • Falha devolve o destino original
  • O resultado é guardado e reutilizado
  • Erros são registrados com o motivo
  • Ambiente local não chama a API
  • A chave usada tem a quantidade de etapas correta para o contexto
  • O código lê status e shortenedUrl, e não campos inventados

Oito itens. Os dois primeiros evitam incidente de segurança; os três seguintes evitam que a sua aplicação quebre por causa de um serviço externo; os três últimos evitam bagunça.

Testando antes de escrever código

Antes de integrar, confirme que a chave funciona. Uma linha no terminal:

curl -s "https://pingulink.com/api?api=SUA_CHAVE&url=https://exemplo.com"

Se voltar JSON com "status": "success", está tudo certo e o problema seguinte será só do seu código. Se voltar erro, você economizou uma tarde de depuração no lugar errado.

As mensagens de erro, e o que cada uma quer dizer

Todas voltam no campo message, sempre com HTTP 200:

MensagemO que aconteceu
Invalid API callFaltou api ou url na chamada
Invalid API tokenChave errada, desativada, ou conta do dono não está ativa
Invalid URLO destino não passou na validação
Invalid aliasAlias fora do formato aceito ou reservado pelo sistema
Alias already takenJá existe, e não é seu com o mesmo destino
Too many requests. Try again later.Passou de 300 chamadas por minuto naquele IP
Internal errorFalha do lado do servidor — vale repetir depois

Os erros mais comuns na integração

SintomaCausa provável
Invalid API token sempreChave com espaço extra ao copiar, ou parâmetro escrito errado — é api, não outro nome
Funciona no terminal, falha no códigoFalta codificar a URL de destino
Funciona local, falha em produçãoVariável de ambiente não configurada no servidor
Resposta vazia com format=textDeu erro — o modo texto não devolve mensagem, só vazio
Links duplicados aos montesSem guardar o resultado; chamada a cada exibição

O segundo é o que mais consome tempo. Um destino com ? ou & quebra a chamada se não for codificado — o parâmetro do destino é interpretado como parâmetro da própria API.

// errado
'...&url=' + destino

// certo
'...&url=' + encodeURIComponent(destino)

Limitando o estrago quando a API cai

Todo serviço externo fica fora do ar em algum momento. A pergunta não é se, é o que o seu sistema faz nesse minuto.

O padrão que resolve chama-se disjuntor: depois de algumas falhas seguidas, pare de tentar por um tempo e devolva o destino original direto.

let falhas = 0, pausaAte = 0;

async function encurtar(destino) {
  if (Date.now() < pausaAte) return destino;   // ainda em pausa

  try {
    const r = await chamarApi(destino);
    falhas = 0;
    return r.ok ? r.short : destino;
  } catch {
    if (++falhas >= 5) pausaAte = Date.now() + 60000;
    return destino;
  }
}

Sem isso, um serviço lento vira um problema seu: cada requisição do seu usuário fica esperando o tempo limite, a fila do seu servidor enche, e o que era indisponibilidade de terceiro vira indisponibilidade sua.

Com o disjuntor, a primeira falha custa quatro segundos e as seguintes custam zero. O usuário recebe o link original e não percebe nada.

Monitorando a integração

Duas métricas bastam, e as duas você já tem se estiver registrando os erros:

  • Proporção de respostas com status: "error". Se ela subir de repente, provavelmente a chave foi revogada ou você bateu no limite de chamadas.
  • Quantos links foram entregues sem encurtar. É receita que deixou de existir, e o número torna visível um problema que ninguém reclamaria.

O segundo é o mais útil dos dois. Uma integração quebrada não gera erro visível para o usuário — ele recebe o link e segue a vida. Sem essa métrica, dá para passar semanas sem perceber que a monetização parou.

Quando não usar a API

Vale dizer, porque programador tende a integrar por reflexo:

  • Se você gera poucos links por mês. Criar à mão no painel é mais rápido que escrever e manter código.
  • Se o seu caso é grupo de Telegram. O gerador de bots já resolve, com convite temporário e remoção automática — coisas que você levaria dias para implementar.
  • Se os destinos são fixos. Um conjunto que não muda pode ser criado uma vez e reutilizado para sempre.

A API compensa quando o destino é dinâmico e o volume justifica o código. Fora disso, ela é trabalho a mais pelo mesmo resultado.

Perguntas frequentes

Existe limite de chamadas?
Sim: 300 chamadas por minuto por IP. Acima disso a resposta vira Too many requests. Try again later. por um período. Guarde o resultado e espace as chamadas.

Posso ter várias chaves?
Pode, e é recomendado — uma por projeto, cada uma com sua configuração de etapas.

A API aceita POST?
Não. É GET com os parâmetros na URL.

Posso escolher o final do link?
Pode, com o parâmetro alias. Se ele já estiver em uso por outra pessoa, a resposta é Alias already taken. Se já for seu e apontar para o mesmo destino, a API devolve o link existente em vez de dar erro — o que torna a chamada segura de repetir.

Como sei quanto cada chave rendeu?
As estatísticas do painel separam por link e por origem. Usar uma chave por projeto é o que torna essa leitura útil — veja como interpretar as estatísticas.

O link gerado por API é diferente?
Não. É o mesmo link, com as mesmas etapas e o mesmo pagamento de um criado à mão no painel.

Comece a ganhar com seus links Conta gratuita, sem cota mínima. Você encurta, compartilha e recebe por visita real. Criar conta grátis
Leia também
✓