Saltar al contenido
cleat.

Para desarrollo y QA

Recibe SMS en un número real de Estados Unidos, directo en tu código.

Una línea de celular real de Estados Unidos, no VoIP, que le entrega cada SMS entrante a tu código. Un webhook firmado sale en cuanto se guarda el mensaje. Una API REST te deja listarlos y consultarlos. Tu equipo sigue viendo la bandeja en vivo, el correo y Telegram. Una línea, USD 24.99 al mes, cancela cuando quieras.

¿Por qué no un número de una plataforma de telecom?

Los números programables de las plataformas de telecom suelen clasificarse como VoIP. El propio artículo de Twilio sobre filtrar VoIP antes de mandar códigos muestra su Lookup marcando un número de Twilio como nonFixedVoip (Twilio). Si un servicio filtra VoIP, su código nunca llega a un número de plataforma. Una línea Cleat es una línea móvil. Esa es toda la razón para usarla. Más sobre tipos de línea.

Primeros pasos

  1. Consigue una línea. Regístrate y suscríbete. Listar tus líneas funciona desde el primer momento; leer los mensajes de una línea responde 403 hasta que el dueño de la cuenta verifica su identidad.
  2. Crea una API key en Ajustes. Empieza con clt_ y se muestra una sola vez. Si prefieres generar un cliente, el contrato completo está descrito en OpenAPI.
  3. Agrega un endpoint de webhook en Ajustes, si quieres recibir pushes: una URL HTTPS pública. Su secreto de firma empieza con whsec_ y se muestra una sola vez.
  4. Lista tus líneas y luego consulta los SMS o espera los webhooks.
Listar las líneas de tu espacio de trabajo
curl https://cleat.so/api/v1/lines \
  -H "Authorization: Bearer $CLEAT_API_KEY"
Respuesta
{
  "data": [
    {
      "id": "8f14e45f-ceea-4b6b-9d3c-2a1f0e7c5b10",
      "phone": "13055550100",
      "label": "Staging sign-ups",
      "status": "active",
      "createdAt": "2026-09-11T10:00:00.000Z"
    }
  ]
}
SMS recibidos después de un momento, del más antiguo al más reciente
curl "https://cleat.so/api/v1/lines/$LINE_ID/messages?after=2026-09-11T10:00:00Z&limit=50" \
  -H "Authorization: Bearer $CLEAT_API_KEY"
Respuesta
{
  "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

Cuando llega un SMS, Cleat manda un POST a cada uno de tus endpoints con este cuerpo JSON, un header cleat-signature y el user agent Cleat-Webhooks/1.0:

Cuerpo de la petición
{
  "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"
  }
}

El header de firma se ve así: t=1789120961,v1=5d41…. v1 es el HMAC-SHA256 en hexadecimal del timestamp, un punto y el cuerpo crudo, con la clave del secreto de firma del endpoint. Verifícalo contra los bytes crudos antes de parsearlos. Rechaza los timestamps viejos para bloquear reenvíos.

Verificar y procesar una 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);

Detalles de la entrega

  • Los endpoints deben ser URLs https:// públicas. Cleat no sigue redirecciones.
  • Responde con cualquier estado 2xx en menos de 10 segundos.
  • La entrega es al menos una vez. Si una falla o se pasa de tiempo, se reintenta: cinco intentos en total, el primero de inmediato y luego a los 30 segundos, 2 minutos, 10 minutos y una hora, enviando los mismos bytes con una firma nueva. Haz que tu handler sea idempotente sobre data.id; el id de un SMS nunca cambia. Ajustes guarda cada intento y puede reenviar cualquier entrega.
  • Si fallan los cinco intentos, ponte al día con la API usando ?after= y el receivedAt del último SMS que procesaste.
  • Mientras la línea está en pausa o su dueño no ha verificado su identidad no se manda nada. Esos SMS se guardan y se pueden leer en cuanto se resuelve el motivo, pero después no se envía ningún webhook por ellos: léelos con ?after=.
  • Hasta cinco endpoints por espacio de trabajo. Ajustes muestra el último estado de cada endpoint y cuántas entregas seguidas han fallado.
  • type es message.received, o test para la entrega de prueba que puedes lanzar desde Ajustes: el mismo data, con sus propios ids. Responde 200 a un tipo que no conozcas; puede que se agreguen más.
  • Si en lugar de tu URL pegas un webhook entrante de Slack o un enlace de workflow de Microsoft Teams, ese endpoint recibe el formato de mensaje de esa app y sin cleat-signature: con una app de chat no hay secreto compartido.
  • code es la mejor suposición de Cleat sobre el código de un solo uso, o null. El body completo siempre está.
  • label dice de quién es el SMS en palabras: un contacto que guardó tu equipo o, si no, el servicio que Cleat reconoció por lo que dice el SMS, con contact y service detrás. Los tres son null cuando no hay certeza. Se agregaron después y no quitan nada: from, body y code siguen igual.
  • Un código dictado en una llamada automática llega igual. La llamada se transcribe y se entrega como un message.received, con la transcripción en body, el número que llamó en from y code lleno. Nada en el payload indica que la entrega fue una llamada y no un SMS.

Referencia de la API

EndpointQué devuelve
GET /api/v1/linesLas líneas del espacio de trabajo de la API key, de la más nueva a la más vieja: id, phone, label, status (active, grace o released) y createdAt.
GET /api/v1/lines/{lineId}/messagesLos SMS de una línea. after (ISO 8601) devuelve los SMS recibidos después de ese momento, del más antiguo al más reciente, para consultar en bucle. before pagina hacia atrás, del más nuevo al más viejo. limit va de 1 a 200, y son 50 por defecto.
URL base https://cleat.so. Autentica con Authorization: Bearer clt_…. Un limit fuera de 1–200 se ajusta al rango, no se rechaza. Errores: 400 si el timestamp está mal formado, 401 si falta la clave, está revocada o venció (code key_expired), 402 mientras la línea está en pausa, 403 hasta que el dueño del espacio de trabajo verifica su identidad (code verify_first), 404 si la línea está fuera del espacio de trabajo de la clave *o* fuera de su alcance: a propósito es la misma respuesta, 429 al pasar el límite, 503 si no se puede comprobar el alcance de la clave.

Límites y permisos

120 peticiones por minuto por API key; al pasarte, la API responde 429, sin cabecera Retry-After, así que el backoff es tuyo. Solo el dueño del espacio de trabajo puede crear API keys y endpoints de webhook, y una clave revocada deja de funcionar de inmediato. También puedes limitar una clave al crearla: a líneas concretas y a una fecha en la que deja de servir, que es lo que hace seguro dársela a un agente, a un job de CI o a alguien externo. Una línea fuera del alcance responde 404, y una clave vencida responde 401 con code key_expired.

Casos que encajan

  • Las cuentas propias de tu empresa, como consolas de nube, registradores de dominios y procesadores de pagos, con los códigos publicados en un canal que vigila la persona de guardia.
  • Staging y QA de tus propios flujos de registro e inicio de sesión, contra un número que se comporta como el teléfono de un cliente.
  • Proyectos personales que necesitan un número de celular de Estados Unidos registrado.

Casos que no

  • Enviar SMS. Cleat Line solo recibe: no puede enviar mensajes, hacer llamadas ni marcar al 911.
  • Pruebas de carga o grupos de números. Cada línea es una suscripción aparte con un dueño verificado. Cleat no está hecho para manejar muchos números.
  • Cuentas que no son tuyas ni de tu empresa.
  • Cualquier cosa que necesite voz en vivo. La API no puede llamar. No hay timbre que contestar, ni audio que transmitir, ni grabación que descargar. Solo queda la transcripción de una llamada después de que terminó. Las llamadas de Cleat Full se contestan y se hacen en la app web, no por la API.

Cómo se compara

Número de plataforma de telecomNúmeros de MailSlurpCleat Line
Tipo de númeroMuchas veces VoIP por clasificación; el Lookup de Twilio marca un número de Twilio como nonFixedVoip“dedicated, non-VoIP mobile numbers” (MailSlurp)Línea de celular real de Estados Unidos, no VoIP
Hecho paraEnviar y recibir a gran escalaQA y pruebas de desarrolloTus propias cuentas, QA y equipos pequeños
Verificación del dueñoKYC de empresa y registro 10DLCNo lo indicaIdentificación oficial y selfie, o solo identificación revisada por una persona
Llevar los SMS al códigoWebhooks y APIAPI y webhooksWebhooks firmados y API REST, además de Telegram, correo y la bandeja
PrecioPor número más por mensajeNo aparece en la páginaUSD 24.99 al mes, SMS entrantes incluidos
Los datos de otras empresas vienen de sus propias páginas, revisadas en septiembre de 2026.

¿Compartes códigos con gente que no programa? Mira 2FA compartido para equipos. Por qué a Google Voice y a otros números de internet no les llegan los códigos: Google Voice y los códigos de verificación. Cómo manejamos la identidad: confianza y seguridad. Las reglas completas de cobro: precio.

Preguntas

¿Hay plan gratis o sandbox?

No. Una línea cuesta USD 24.99 al mes, cancelas cuando quieras, y sus mensajes quedan bloqueados hasta que su dueño verifica su identidad.

¿Puedo enviar SMS por la API?

No. Cleat Line recibe; nunca envía.

¿Y si un servicio dicta el código en una llamada en vez de mandarlo por SMS?

La llamada se transcribe y llega a tu webhook y a la API como un mensaje normal, con el código extraído y el número que llamó en from. Ningún campo indica que fue una llamada.

¿Hay límites de peticiones?

Sí: 120 peticiones por minuto por API key. Las entregas de webhook no cuentan para ese límite.

¿Qué tan rápido salen los webhooks?

Cleat manda el POST a tus endpoints en cuanto guardó el SMS, junto con la bandeja en vivo, el correo y Telegram. No hemos publicado latencia medida, así que no damos un número.

¿Puedo tener más de un número?

Puedes agregar líneas a un espacio de trabajo, y cada una es su propia suscripción de USD 24.99. Cleat no está hecho para manejar muchos números.

¿Guardan mis mensajes?

Los SMS se guardan hasta que borras el espacio de trabajo o tu cuenta. La Política de privacidad, en inglés tiene los detalles.

Fuentes

Los datos sobre otras empresas vienen de sus propias páginas, revisadas en septiembre 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/

Consigue una línea y una API key.

USD 24.99 al mes, cancela cuando quieras.

  • Cada dueño con identidad verificada
  • SMS privados para tu equipo
  • Cancela cuando quieras