Pular para o conteúdo
cleat.

Para desenvolvimento e QA

Receba SMS num número americano de verdade, direto no seu código.

Uma linha móvel americana de verdade, não VoIP, que entrega cada SMS recebido para o seu código. Um webhook assinado sai assim que a mensagem é guardada. Uma API REST lista e consulta. A equipe continua vendo a caixa de entrada ao vivo, o e-mail e o Telegram. Uma linha, US$ 24,99 por mês, cancele quando quiser.

Por que não um número de plataforma de telecom?

Números programáveis de plataformas de telecom costumam ser classificados como VoIP. O próprio texto da Twilio sobre filtrar VoIP antes de mandar códigos mostra o Lookup dela marcando um número da Twilio como nonFixedVoip (Twilio). Se um serviço filtra VoIP, o código dele nunca chega num número de plataforma. Uma linha Cleat é uma linha móvel. É essa a razão de usar uma. Mais sobre tipos de linha.

Primeiros passos

  1. Pegue uma linha. Crie a conta e assine. Listar suas linhas funciona na hora; ler as mensagens de uma linha responde 403 até o dono da conta verificar a identidade.
  2. Crie uma API key em Configurações. Ela começa com clt_ e aparece uma vez só.
  3. Adicione um endpoint de webhook em Configurações, se quiser receber pushes: uma URL HTTPS pública. O segredo de assinatura começa com whsec_ e aparece uma vez só.
  4. Liste suas linhas e depois consulte os SMS ou espere os webhooks.
Listar as linhas do seu espaço de trabalho
curl https://cleat.so/api/v1/lines \
  -H "Authorization: Bearer $CLEAT_API_KEY"
Resposta
{
  "data": [
    {
      "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10",
      "phone": "13055550100",
      "label": "Staging sign-ups",
      "status": "active",
      "createdAt": "2026-09-11T10:00:00.000Z"
    }
  ]
}
SMS recebidos depois de um momento, do mais antigo para o mais novo
curl "https://cleat.so/api/v1/lines/$LINE_ID/messages?after=2026-09-11T10:00:00Z&limit=50" \
  -H "Authorization: Bearer $CLEAT_API_KEY"
Resposta
{
  "data": [
    {
      "id": "c9a7e0d2-5b1f-4e8a-9f3c-6d2b1a0e4f77",
      "line": { "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10", "phone": "13055550100", "label": "Staging sign-ups" },
      "from": "32665",
      "body": "704118 is your Facebook confirmation code",
      "code": "704118",
      "receivedAt": "2026-09-11T10:02:41.000Z",
      "service": { "id": "facebook", "name": "Facebook", "color": "#0866FF" },
      "contact": null,
      "label": "Facebook"
    }
  ]
}

Webhooks

Quando um SMS chega, a Cleat manda um POST para cada um dos seus endpoints com este corpo JSON, um header cleat-signature e o user agent Cleat-Webhooks/1.0:

Corpo da requisição
{
  "type": "message.received",
  "data": {
    "id": "c9a7e0d2-5b1f-4e8a-9f3c-6d2b1a0e4f77",
    "line": { "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10", "phone": "13055550100", "label": "Staging sign-ups" },
    "from": "32665",
    "body": "704118 is your Facebook confirmation code",
    "code": "704118",
    "receivedAt": "2026-09-11T10:02:41.000Z",
    "service": { "id": "facebook", "name": "Facebook", "color": "#0866FF" },
    "contact": null,
    "label": "Facebook"
  }
}

O header de assinatura fica assim: t=1789120961,v1=5d41…. v1 é o HMAC-SHA256 em hexadecimal do timestamp, de um ponto e do corpo cru, com a chave do segredo de assinatura do endpoint. Confira contra os bytes crus antes de fazer o parse. Recuse timestamps antigos para bloquear reenvios.

Conferir e tratar uma entrega (Node.js, Express)
import crypto from "node:crypto";
import express from "express";

const app = express();
const secret = process.env.CLEAT_WEBHOOK_SECRET; // whsec_…

// cleat-signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">
function verified(header, body) {
  const parts = Object.fromEntries(String(header).split(",").map((part) => part.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${body}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && parts.v1?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
}

app.post("/cleat-webhook", express.raw({ type: "application/json" }), (req, res) => {
  const body = req.body.toString("utf8");
  if (!verified(req.get("cleat-signature"), body)) return res.sendStatus(401);

  const { type, data } = JSON.parse(body);
  if (type === "message.received") {
    // data.code is Cleat's best guess at a one-time code; data.body is the full text.
    console.log(data.line.phone, data.from, data.code ?? data.body);
  }
  res.sendStatus(200);
});

app.listen(3000);

Detalhes da entrega

  • Os endpoints precisam ser URLs https:// públicas. A Cleat não segue redirecionamentos.
  • Responda com qualquer status 2xx em até 10 segundos.
  • A entrega é pelo menos uma vez. Se uma falha ou estoura o tempo, ela é tentada de novo: cinco tentativas no total, a primeira na hora e depois com 30 segundos, 2 minutos, 10 minutos e uma hora, mandando os mesmos bytes com uma assinatura nova. Faça o seu handler ser idempotente no data.id; o id de um SMS nunca muda. Configurações guarda cada tentativa e pode reenviar qualquer entrega.
  • Se as cinco tentativas falharem, se atualize pela API com ?after= e o receivedAt do último SMS que você tratou.
  • Enquanto a linha está suspensa ou o dono dela não verificou a identidade, nada é enviado. Esses SMS ficam guardados e podem ser lidos assim que o motivo se resolve, mas nenhum webhook é mandado por eles depois: leia com ?after=.
  • Até cinco endpoints por espaço de trabalho. Configurações mostra o último status de cada endpoint e quantas entregas seguidas falharam.
  • type é message.received, ou test para a entrega de teste que você dispara em Configurações: o mesmo data, com ids próprios. Responda 200 a um tipo que você não conhece; outros podem aparecer.
  • Se em vez da sua URL você colar um webhook de entrada do Slack ou um link de workflow do Microsoft Teams, aquele endpoint recebe o formato de mensagem do próprio app e sem cleat-signature: com um app de chat não existe segredo compartilhado.
  • code é o melhor palpite da Cleat para o código de uso único, ou null. O body completo está sempre lá.
  • label diz de quem é o SMS em palavras: um contato que a sua equipe salvou ou, senão, o serviço que o Cleat reconheceu pelo que o SMS diz, com contact e service por trás. Os três vêm null quando não dá para ter certeza. Foram adicionados depois e não tiram nada: from, body e code continuam iguais.
  • Um código ditado numa ligação automática chega do mesmo jeito. A ligação é transcrita e entregue como um message.received, com a transcrição em body, o número que ligou em from e o code preenchido. Nada no payload indica que a entrega foi uma ligação em vez de um SMS.

Referência da API

EndpointO que devolve
GET /api/v1/linesAs linhas do espaço de trabalho da API key, da mais nova para a mais antiga: id, phone, label, status (active, grace ou released) e createdAt.
GET /api/v1/lines/{lineId}/messagesOs SMS de uma linha. after (ISO 8601) devolve os SMS recebidos depois daquele momento, do mais antigo para o mais novo, para consultar em loop. before pagina para trás, do mais novo para o mais antigo. limit vai de 1 a 200, e são 50 por padrão.
URL base https://cleat.so. Autentique com Authorization: Bearer clt_…. Um limit fora de 1–200 é ajustado ao intervalo, não recusado. Erros: 400 para timestamp mal formado, 401 para chave faltando, revogada ou expirada (code key_expired), 402 enquanto a linha está suspensa, 403 até o dono do espaço de trabalho verificar a identidade (code verify_first), 404 para uma linha fora do espaço de trabalho da chave *ou* fora do escopo dela — de propósito é a mesma resposta, 429 acima do limite, 503 se o escopo da chave não puder ser verificado.

Limites e permissões

120 requisições por minuto por API key; passou disso, a API responde 429, sem cabeçalho Retry-After, então o backoff é seu. Só o dono do espaço de trabalho cria API keys e endpoints de webhook, e uma chave revogada para de funcionar na hora. Você também pode limitar uma chave na criação: a linhas específicas e a uma data em que ela deixa de valer, o que é o que torna seguro entregá-la a um agente, a um job de CI ou a um terceiro. Uma linha fora do escopo responde 404, e uma chave expirada responde 401 com code key_expired.

Casos que encaixam

  • As contas da sua própria empresa, como consoles de nuvem, registros de domínio e gateways de pagamento, com os códigos indo para um canal que a pessoa de plantão acompanha.
  • Staging e QA dos seus próprios fluxos de cadastro e login, contra um número que se comporta como o celular de um cliente.
  • Projetos pessoais que precisam de um número de celular americano no cadastro.

Casos que não encaixam

  • Enviar SMS. A Cleat Line só recebe: não envia mensagens, não faz chamadas e não liga para o 911.
  • Teste de carga ou pilhas de números. Cada linha é uma assinatura separada, com um dono verificado. A Cleat não foi feita para ter muitos números.
  • Contas que não são suas nem da sua empresa.
  • Qualquer coisa que precise de voz ao vivo. A API não liga para fora. Não tem chamada para atender, áudio para transmitir nem gravação para baixar. Só a transcrição de uma ligação depois que ela acabou. As ligações da Cleat Full são atendidas e feitas no app web, não pela API.

Como se compara

Número de plataforma de telecomNúmeros da MailSlurpCleat Line
Tipo de númeroMuitas vezes VoIP na classificação; o Lookup da Twilio marca um número da Twilio como nonFixedVoip“dedicated, non-VoIP mobile numbers” (MailSlurp)Linha móvel americana de verdade, não VoIP
Feito paraEnviar e receber em escalaQA e testes de desenvolvimentoSuas próprias contas, QA e equipes pequenas
Verificação do donoKYC de empresa e registro 10DLCNão informaDocumento oficial e selfie, ou só documento revisado por uma pessoa
Levar os SMS para o códigoWebhooks e APIAPI e webhooksWebhooks assinados e API REST, além de Telegram, e-mail e a caixa de entrada
PreçoPor número mais por mensagemNão aparece na páginaUS$ 24,99 por mês, SMS recebidos inclusos
Os dados de outras empresas vêm das páginas delas, conferidas em setembro de 2026.

Precisa dividir códigos com gente que não programa? Veja 2FA compartilhado para equipes. Por que o Google Voice e outros números de internet perdem códigos: Google Voice e os códigos de verificação. Como tratamos identidade: confiança e segurança. As regras de cobrança: preço.

Perguntas

Tem plano grátis ou sandbox?

Não. Uma linha custa US$ 24,99 por mês, cancele quando quiser, e as mensagens ficam bloqueadas até o dono verificar a identidade.

Dá para enviar SMS pela API?

Não. A Cleat Line recebe; ela nunca envia.

E se um serviço ditar o código numa ligação em vez de mandar SMS?

A ligação é transcrita e chega no seu webhook e na API como uma mensagem comum, com o código extraído e o número que ligou em from. Nenhum campo indica que foi uma ligação.

Tem limite de requisições?

Tem: 120 requisições por minuto por API key. As entregas de webhook não contam nesse limite.

Em quanto tempo os webhooks disparam?

A Cleat manda o POST para os seus endpoints assim que guardou o SMS, junto com a caixa ao vivo, o e-mail e o Telegram. Não publicamos latência medida, então não damos um número.

Dá para ter mais de um número?

Você pode adicionar linhas a um espaço de trabalho, e cada uma é uma assinatura própria de US$ 24,99. A Cleat não foi feita para ter muitos números.

Vocês guardam minhas mensagens?

Os SMS ficam guardados até você apagar o espaço de trabalho ou a conta. A Política de Privacidade, em inglês tem os detalhes.

Fontes

Os dados sobre outras empresas vêm das páginas delas, conferidas em setembro de 2026.

  1. Twilio, filtering VoIP numbers before sending codes https://www.twilio.com/en-us/blog/filter-voip-before-otp-verification
  2. MailSlurp, phone numbers https://www.mailslurp.com/product/phone-number-sms-service/

Pegue uma linha e uma API key.

US$ 24,99 por mês, cancele quando quiser.

  • Todo dono com identidade verificada
  • SMS privados para sua equipe
  • Cancele quando quiser