API para desarrolladores
Venda números temporales en su sitio web o aplicación y reciba códigos de verificación mediante la API.
Inicio rápido
- Crea una cuenta y solicita acceso en Revender números en el panel. La aprobación es manual.
- Tras la aprobación, crea una clave de prueba ativa_test_ y guárdala en tu servidor.
- Sustituye $ATIVA_API_KEY por tu clave de prueba y haz la primera solicitud que aparece abajo.
Ejemplo del modo de prueba gratuito: importes ficticios, siempre en BRL. Esta respuesta usa la opción real del simulador sin comprar un número.
curl 'https://www.ativasms.store/api/v1/opcoes?servico=wa&pais=187' \
-H "Authorization: Bearer $ATIVA_API_KEY"Respuesta (HTTP 200)
[
{
"opcao": "op_000000000001",
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"prazo_min": 20,
"taxa_sucesso": null,
"estoque": 100,
"recomendada": false
}
]Explore el programa de reventa y venda a su propio precio →
1. Qué hace y cómo obtener acceso
La API permite revender números SMS temporales desde su propio sitio web o aplicación. Sus clientes no necesitan visitar Ativa SMS.
Cree una cuenta y solicite acceso mediante Revender números en el menú del perfil del dashboard. Es obligatorio aceptar los Términos de reventa; también se aplican los Términos de uso. Una vez aprobado, cree claves en Dashboard → API.
2. URL base y formato de datos
URL base: https://www.ativasms.store/api/v1. Envíe JSON UTF-8 con Content-Type: application/json para los cuerpos de las solicitudes. Las respuestas son JSON e incluyen Cache-Control: no-store.
Los importes son céntimos enteros: moeda es BRL o USD según su cuenta; 83 céntimos BRL equivalen a R$ 0.83. El modo de prueba siempre usa BRL. Las fechas son ISO 8601 UTC. Los teléfonos usan formato internacional +código-de-país, o null mientras la reserva sigue en curso.
Los ejemplos son ilustrativos y siguen los formatos reales de respuesta; los ejemplos de compra usan datos ficticios de prueba. Use los códigos de servicio y las opciones devueltas por la API; los precios live varían. Los ejemplos curl leen ATIVA_API_KEY de una variable de entorno de su servidor.
Especificación OpenAPI 3.1 para herramientas y agentes de IA: /openapi.json.
3. Autenticación
Envíe Authorization: Bearer <key> en cada endpoint. Las claves empiezan por ativa_live_ para producción o ativa_test_ para pruebas. No se aceptan claves en parámetros de consulta ni en cuerpos.
Una clave se muestra una sola vez, al crearla. Guárdela en su servidor, nunca en el navegador o la aplicación del cliente. Una cuenta puede tener hasta 5 claves activas, contando juntas las claves live y test. Revoque y sustituya las claves perdidas o expuestas en el dashboard. Si hay una restricción de IP configurada, las solicitudes también deben cumplirla.
Los fallos de autenticación devuelven la misma respuesta HTTP 401 sin revelar el motivo:
{
"erro": "nao_autorizado",
"mensagem": "Chave de API ausente, inválida ou revogada."
}
4. Límites de uso
Los límites predeterminados pueden ajustarse para cada revendedor. Consulte los límites actuales de su cuenta en el dashboard:
| Límite | Predeterminado |
|---|---|
| Solicitudes por minuto | 120 |
| Compras/sustituciones por minuto | 20 |
| Números esperando SMS simultáneamente | 20 |
| Intentos sin código por cuenta en 24 h | 100 |
| Intentos sin código por cliente_ref en 24 h | 15 |
Las tasas de solicitudes y compras suman todas las claves de la cuenta dentro del mismo modo. Los contadores test y live están separados y usan los mismos límites configurados. Las cancelaciones, sustituciones y caducidades sin SMS consumen intentos; cada número con código restituye 5 intentos, hasta el límite. Los fallos de entrega no cuentan. Los límites live de la cuenta para números abiertos e intentos también abarcan las compras hechas en el sitio web.
Superar las tasas de solicitudes o compras devuelve HTTP 429 muitas_requisicoes y Retry-After: 60 (segundos). Otros límites devuelven 429 con su código específico y sin Retry-After: espere a que se liberen números abiertos o intentos, según corresponda.
5. Idempotencia y precio máximo
Idempotency-Key es obligatorio para compras y sustituciones: 1–64 letras, dígitos o . _ : -. Use una clave nueva para cada operación deseada y la misma para los reintentos. Las claves tienen ámbito de cuenta y modo; las compras y sustituciones comparten ese ámbito. No reutilice una clave para otro cliente o pedido.
Repetir una clave registrada devuelve HTTP 200 con el mismo número y su estado actual, aunque el cuerpo haya cambiado; una compra nueva devuelve 201. Las consultas live no terminan a las 24 h: la clave se refiere a ese número mientras exista su registro. El historial de prueba se conserva durante 30 días. Reiniciar el saldo de prueba conserva el historial y la idempotencia.
preco_maximo_centavos es el cargo máximo que acepta en la moneda de su cuenta. Si el precio actual lo supera, la API devuelve preco_acima_do_maximo con preco_centavos y opcoes, sin comprar. preco_centavos se descuenta de su saldo; preco_site_centavos es el precio de referencia del sitio web. El precio se comprueba de nuevo al comprar.
6. Endpoints y ejemplos
GET /saldo
Sin parámetros. Devuelve el saldo en la moneda de la cuenta (BRL o USD). El modo de prueba siempre usa BRL y fondos ficticios.
curl "https://www.ativasms.store/api/v1/saldo" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
{
"saldo_centavos": 10000,
"moeda": "BRL"
}
GET /servicos
Sin parámetros. Devuelve todos los servicios disponibles, sin duplicados ni servicios bloqueados. El ejemplo muestra una entrada; el modo de prueba también incluye teste_falha (Teste sem código). Los nombres de campos y las etiquetas de servicios de la API permanecen en portugués independientemente del idioma de la documentación.
curl "https://www.ativasms.store/api/v1/servicos" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
[
{
"codigo": "wa",
"nome": "WhatsApp"
}
]
GET /paises
Sin parámetros. Devuelve todos los países. Use codigo en consultas y compras; iso está en mayúsculas y ddi es el prefijo telefónico. El ejemplo muestra una entrada.
curl "https://www.ativasms.store/api/v1/paises" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
[
{
"codigo": 73,
"iso": "BR",
"nome": "Brasil",
"ddi": "+55"
}
]
GET /opcoes
Parámetros de consulta obligatorios: servico (un código de la lista de servicios) y pais (un código numérico de país). Devuelve hasta 6 opciones en orden ascendente de preco_centavos; el resultado puede ser []. opcao es un identificador opaco: op_ seguido de 12 caracteres hexadecimales. Envíe el valor devuelto sin interpretarlo. preco_centavos es el cargo del revendedor; preco_site_centavos es el precio de referencia del sitio web, ambos en la moneda indicada. prazo_min es el plazo; taxa_sucesso puede ser null; estoque indica disponibilidad y recomendada marca una opción sugerida. Este ejemplo usa la opción ficticia de prueba.
curl "https://www.ativasms.store/api/v1/opcoes?servico=wa&pais=73" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
[
{
"opcao": "op_000000000001",
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"prazo_min": 20,
"taxa_sucesso": null,
"estoque": 100,
"recomendada": false
}
]
POST /numeros
Campos JSON obligatorios: servico (1–20 letras minúsculas, dígitos o _; un servicio permitido), pais (un código entero de país válido), preco_maximo_centavos (un entero positivo) y cliente_ref (un identificador anónimo, 1–64 letras, dígitos o . _ : -; nunca una dirección de correo electrónico ni un identificador personal). opcao es opcional y puede ser null; omitirlo selecciona la opción más barata. Envíe Idempotency-Key. Una compra nueva devuelve 201; una repetición devuelve 200 con el mismo id y el estado actual, sin otro cargo. Este es un ejemplo de compra de prueba.
curl -X POST "https://www.ativasms.store/api/v1/numeros" \
-H "Authorization: Bearer $ATIVA_API_KEY" \
-H "Idempotency-Key: compra_abc123" \
-H "Content-Type: application/json" \
-d '{"servico":"wa","pais":73,"opcao":"op_000000000001","preco_maximo_centavos":83,"cliente_ref":"cliente_abc123"}'
HTTP 201
{
"id": "5f0c0000-0000-4000-8000-000000000001",
"servico": "wa",
"servico_nome": "WhatsApp",
"pais": 73,
"telefone": "+12025550123",
"status": "aguardando_sms",
"motivo": null,
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:00:00.000Z",
"cancelavel_em": "2026-10-08T12:02:00.000Z",
"expira_em": "2026-10-08T12:20:00.000Z",
"encerrado_em": null,
"substitui_id": null,
"cliente_ref": "cliente_abc123",
"sms": []
}
GET /numeros/{id}
Ruta: /numeros/{id}, donde id es el UUID del número. Solo son visibles las compras por API pertenecientes a esta cuenta y modo; un número de otro propietario, una compra del sitio web o un UUID inválido devuelve nao_encontrado. Los números abiertos se actualizan antes de responder, hasta 60 actualizaciones/min por clave live; las solicitudes posteriores devuelven el último estado disponible (200, sin un 429 adicional de sincronización). Este ejemplo muestra un código de prueba recibido.
curl "https://www.ativasms.store/api/v1/numeros/5f0c0000-0000-4000-8000-000000000001" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
{
"id": "5f0c0000-0000-4000-8000-000000000001",
"servico": "wa",
"servico_nome": "WhatsApp",
"pais": 73,
"telefone": "+12025550123",
"status": "recebido",
"motivo": null,
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:00:00.000Z",
"cancelavel_em": "2026-10-08T12:02:00.000Z",
"expira_em": "2026-10-08T12:20:00.000Z",
"encerrado_em": null,
"substitui_id": null,
"cliente_ref": "cliente_abc123",
"sms": [
{
"codigo": "123456",
"texto": "Seu código de teste: 123456",
"recebido_em": "2026-10-08T12:00:20.000Z"
}
]
}
GET /numeros
Parámetros de consulta opcionales: status (un estado documentado del número), cliente_ref (el mismo formato que en la compra), pagina (1–1000, predeterminado 1). Devuelve hasta 50 compras por API por página para esta cuenta y modo, las más recientes primero. tem_mais indica otra página. Listar números live no fuerza su actualización; consulte un número individual para actualizarlo.
curl "https://www.ativasms.store/api/v1/numeros?status=aguardando_sms&cliente_ref=cliente_abc123&pagina=1" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
{
"numeros": [
{
"id": "5f0c0000-0000-4000-8000-000000000001",
"servico": "wa",
"servico_nome": "WhatsApp",
"pais": 73,
"telefone": "+12025550123",
"status": "aguardando_sms",
"motivo": null,
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:00:00.000Z",
"cancelavel_em": "2026-10-08T12:02:00.000Z",
"expira_em": "2026-10-08T12:20:00.000Z",
"encerrado_em": null,
"substitui_id": null,
"cliente_ref": "cliente_abc123",
"sms": []
}
],
"pagina": 1,
"tem_mais": false
}
POST /numeros/{id}/cancelar
Ruta: /numeros/{id}/cancelar. Campo opcional del cuerpo: motivo (desistiu, banido, ja_tem_dono, pede_outra_coisa u outro; predeterminado outro). Sin código y después de cancelavel_em, cierra el número y reembolsa el saldo. Antes de ese momento: 409 cedo con segundos. Un número ya recibido devuelve nao_cancelavel; codigo_recebido puede producirse si llega un código durante la cancelación. Devuelve 200 con el número cerrado. Este ejemplo usa teste_falha después de dos minutos.
curl -X POST "https://www.ativasms.store/api/v1/numeros/5f0c0000-0000-4000-8000-000000000001/cancelar" \
-H "Authorization: Bearer $ATIVA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"motivo":"desistiu"}'
HTTP 200
{
"id": "5f0c0000-0000-4000-8000-000000000001",
"servico": "teste_falha",
"servico_nome": "Teste sem código",
"pais": 73,
"telefone": "+12025550123",
"status": "cancelado",
"motivo": "desistiu",
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:00:00.000Z",
"cancelavel_em": "2026-10-08T12:02:00.000Z",
"expira_em": "2026-10-08T12:20:00.000Z",
"encerrado_em": "2026-10-08T12:02:01.000Z",
"substitui_id": null,
"cliente_ref": "cliente_abc123",
"sms": []
}
POST /numeros/{id}/trocar
Ruta: /numeros/{id}/trocar. Campo obligatorio del cuerpo: preco_maximo_centavos (entero positivo); opcao y motivo son opcionales, con los formatos anteriores. El servicio, el país y cliente_ref se heredan del número original. Exige Idempotency-Key y un número aguardando_sms con teléfono, sin código y con la espera de cancelación cumplida. El precio se comprueba antes de cerrar el número anterior. El anterior pasa a trocado y se reembolsa; una nueva compra devuelve 201 (una repetición devuelve 200). Si la nueva compra falla después del reembolso, el anterior permanece trocado: consúltelo y gestione el error. Este ejemplo sustituye un número teste_falha después de dos minutos.
curl -X POST "https://www.ativasms.store/api/v1/numeros/5f0c0000-0000-4000-8000-000000000001/trocar" \
-H "Authorization: Bearer $ATIVA_API_KEY" \
-H "Idempotency-Key: troca_abc123" \
-H "Content-Type: application/json" \
-d '{"preco_maximo_centavos":83,"motivo":"banido"}'
HTTP 201
{
"id": "5f0c0000-0000-4000-8000-000000000002",
"servico": "teste_falha",
"servico_nome": "Teste sem código",
"pais": 73,
"telefone": "+12025550124",
"status": "aguardando_sms",
"motivo": null,
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:02:01.000Z",
"cancelavel_em": "2026-10-08T12:04:01.000Z",
"expira_em": "2026-10-08T12:22:01.000Z",
"encerrado_em": null,
"substitui_id": "5f0c0000-0000-4000-8000-000000000001",
"cliente_ref": "cliente_abc123",
"sms": []
}
POST /numeros/{id}/concluir
Ruta: /numeros/{id}/concluir. Sin cuerpo. Confirma que el código se ha utilizado y cierra un número recebido sin reembolso. Devuelve 200 con el número concluido; repetir la finalización o finalizar sin código devuelve 409 nao_concluivel.
curl -X POST "https://www.ativasms.store/api/v1/numeros/5f0c0000-0000-4000-8000-000000000001/concluir" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
{
"id": "5f0c0000-0000-4000-8000-000000000001",
"servico": "wa",
"servico_nome": "WhatsApp",
"pais": 73,
"telefone": "+12025550123",
"status": "concluido",
"motivo": null,
"preco_centavos": 83,
"preco_site_centavos": 120,
"moeda": "BRL",
"criado_em": "2026-10-08T12:00:00.000Z",
"cancelavel_em": "2026-10-08T12:02:00.000Z",
"expira_em": "2026-10-08T12:20:00.000Z",
"encerrado_em": "2026-10-08T12:01:00.000Z",
"substitui_id": null,
"cliente_ref": "cliente_abc123",
"sms": [
{
"codigo": "123456",
"texto": "Seu código de teste: 123456",
"recebido_em": "2026-10-08T12:00:20.000Z"
}
]
}
GET /extrato
Parámetro de consulta opcional: pagina (1–1000, predeterminado 1). Devuelve hasta 50 movimientos de la cuenta, los más recientes primero (compra, reembolso, recarga, ajuste), incluidos los movimientos del sitio web en modo live. valor_centavos tiene signo: negativo para débitos, positivo para créditos; saldo_apos_centavos es el saldo posterior. numero_id es null cuando el movimiento no está relacionado con un número; descricao puede ser null. El extracto no incluye moeda: use la moneda de GET /saldo. Los extractos de prueba están separados y siempre usan BRL.
curl "https://www.ativasms.store/api/v1/extrato?pagina=1" \
-H "Authorization: Bearer $ATIVA_API_KEY"
HTTP 200
{
"movimentacoes": [
{
"id": 42,
"tipo": "compra",
"valor_centavos": -83,
"saldo_apos_centavos": 9917,
"descricao": "Número WhatsApp",
"numero_id": "5f0c0000-0000-4000-8000-000000000001",
"criado_em": "2026-10-08T12:00:00.000Z"
}
],
"pagina": 1,
"tem_mais": false
}
7. Ciclo de vida del número
Después de comprar, muestre el teléfono a su cliente y pídale que solicite el código en la aplicación de destino. Comprar un número no solicita automáticamente un SMS. El modo de prueba simula la entrega.
| Status | Significado |
|---|---|
| aguardando_sms | En espera; un teléfono null puede significar que la reserva sigue en curso. |
| recebido | Llegó al menos un SMS; no se puede cancelar ni sustituir. |
| concluido | Cerrado tras recibir un código, manualmente o al vencer el plazo. |
| cancelado | Cancelado sin código y reembolsado. |
| trocado | El número anterior se cerró y reembolsó durante una sustitución. |
| expirado | Venció el plazo sin código; reembolso automático. |
| falhou | Falló la compra/entrega; fondos devueltos. |
Los objetos de número incluyen servico_nome, motivo, moeda, preco_site_centavos (puede ser null), encerrado_em, substitui_id (el id del número anterior en una sustitución) y sms. Las fechas de cancelación, caducidad y cierre pueden ser null. Cada SMS incluye codigo y texto (ambos pueden ser null) y recebido_em.
Respete cancelavel_em: algunas opciones permiten cancelar de inmediato; otras requieren 2 min. Un error cedo indica la espera restante:
{
"erro": "cedo",
"mensagem": "Este número ainda não pode ser cancelado. Tente de novo após `segundos`.",
"segundos": 45
}
Sin SMS dentro del plazo, los fondos vuelven automáticamente al saldo. Los números live pueden tener un período de gracia de 5 min para SMS tardíos antes del cierre. Siga expira_em y el estado devuelto. Completar un número tras llegar un código lo cierra sin reembolso; los números recibidos no pueden cancelarse ni sustituirse. Durante una sustitución, un fallo al comprar el nuevo número puede dejar el anterior trocado y reembolsado.
8. Errores
Los errores incluyen erro y mensagem (en portugués). Gestione el código en lugar de comparar el mensaje. Los campos adicionales pueden incluir campos, segundos, preco_centavos y opcoes.
| Código | HTTP | Cuándo ocurre |
|---|---|---|
nao_autorizado |
401 | Clave ausente, inválida o revocada, IP no permitida o acceso suspendido; la misma respuesta genérica oculta la causa. |
parametro_invalido |
400 | Campo, consulta o cuerpo inválido; puede incluir campos con la lista de campos que corregir. |
servico_bloqueado |
400 | Se ha solicitado un servicio bloqueado. |
idempotencia_obrigatoria |
400 | Idempotency-Key ausente o con formato incorrecto en la compra o sustitución. |
saldo_insuficiente |
402 | Fondos insuficientes para la compra. |
cliente_bloqueado |
403 | cliente_ref está bloqueado para esta cuenta. |
nao_encontrado |
404 | UUID inválido o número no disponible para esta cuenta y modo. |
sem_numeros |
409 | No hay números disponibles para ese servicio y país; sin cargo. |
opcao_indisponivel |
409 | La opción seleccionada ya no está disponible; incluye las opcoes actuales. |
preco_acima_do_maximo |
409 | El precio actual supera el máximo; incluye preco_centavos y opcoes, sin cargo. |
preco_subiu |
409 | El precio cambió durante la compra; se reembolsó el importe. |
cedo |
409 | Demasiado pronto para cancelar o sustituir; incluye la espera en segundos. |
codigo_recebido |
409 | Un código recibido impide la sustitución, o llegó durante la cancelación. |
nao_cancelavel |
409 | El estado no permite cancelar, incluido un número ya recebido. |
nao_trocavel |
409 | Sin teléfono, un número cerrado o un estado incompatible con la sustitución. |
nao_concluivel |
409 | El número no está recebido, incluida una segunda solicitud de finalización. |
muitas_requisicoes |
429 | Se superó la tasa de solicitudes o compras; Retry-After: 60. |
limite_abertas |
429 | Demasiados números esperando SMS; sin Retry-After. |
limite_tentativas |
429 | Se agotaron los intentos sin código de la cuenta en 24 h; sin Retry-After. |
limite_tentativas_cliente |
429 | Se agotaron los intentos sin código de este cliente_ref en 24 h; sin Retry-After. |
erro_fornecedor |
502 | Falló la entrega del número; se reembolsó el importe. |
sem_confirmacao |
502 | Compra sin confirmar; reintente con la misma Idempotency-Key. Si no se entrega un número en 10 min, se reembolsa el importe. |
erro_interno |
500 | Fallo inesperado; reintente compras y sustituciones con la misma clave de idempotencia. |
9. Webhooks y firmas
Configure una URL HTTPS pública en Dashboard → API. Se rechazan direcciones internas, credenciales y fragmentos en la URL; no se siguen redirecciones. El secreto se muestra una vez al crearlo o renovarlo: guárdelo en su servidor. Cambiar solo la URL conserva el secreto; eliminar el webhook borra su configuración. Cada intento de entrega usa la URL y el secreto actuales.
Los eventos se envían como solicitudes POST JSON:
numero.codigo_recebido: una notificación por cada SMS nuevo;dados.smses un objeto con codigo, texto y recebido_em, en lugar de un array de SMS. Un número puede recibir varias notificaciones, incluidos SMS tardíos tras el cierre.numero.encerrado: concluido, cancelado, trocado, expirado o falhou; incluye motivo (puede ser null), encerrado_em y estornado_centavos (cero sin reembolso), en la moneda indicada.teste.ping: una prueba de entrega solicitada en el dashboard, sin número ni cargo.
El sobre contiene id (el UUID de la notificación, distinto de dados.id), evento, criado_em y dados. Los eventos de números incluyen id, cliente_ref, servico, pais, telefone (o null), status y moeda en dados. Los eventos de números de prueba añaden modo: "test" al sobre; los eventos live y el ping del dashboard omiten ese campo. Ejemplos:
{
"id": "a7100000-0000-4000-8000-000000000001",
"evento": "numero.codigo_recebido",
"criado_em": "2026-10-08T12:00:20.000Z",
"modo": "test",
"dados": {
"id": "5f0c0000-0000-4000-8000-000000000001",
"cliente_ref": "cliente_abc123",
"servico": "wa",
"pais": 73,
"telefone": "+12025550123",
"status": "recebido",
"moeda": "BRL",
"sms": {
"codigo": "123456",
"texto": "Seu código de teste: 123456",
"recebido_em": "2026-10-08T12:00:20.000Z"
}
}
}
{
"id": "a7100000-0000-4000-8000-000000000002",
"evento": "numero.encerrado",
"criado_em": "2026-10-08T12:20:00.000Z",
"modo": "test",
"dados": {
"id": "5f0c0000-0000-4000-8000-000000000001",
"cliente_ref": "cliente_abc123",
"servico": "teste_falha",
"pais": 73,
"telefone": "+12025550123",
"status": "expirado",
"moeda": "BRL",
"motivo": "prazo",
"encerrado_em": "2026-10-08T12:20:00.000Z",
"estornado_centavos": 83
}
}
{
"id": "a7100000-0000-4000-8000-000000000003",
"evento": "teste.ping",
"criado_em": "2026-10-08T12:00:00.000Z",
"dados": {
"mensagem": "Teste de webhook do Ativa SMS"
}
}
Cabeceras:
X-Ativa-Evento: nombre del evento.X-Ativa-Timestamp: marca de tiempo Unix en segundos, renovada en cada intento.X-Ativa-Assinatura: HMAC-SHA256 hexadecimal en minúsculas sobre los bytes UTF-8 detimestamp + "." + body, usando el secreto como texto, sin decodificarlo de hexadecimal.
Verifique el cuerpo original antes de interpretar el JSON; volver a serializarlo puede cambiar la firma. Rechace marcas de tiempo que difieran más de 5 minutos de la hora actual, en cualquier dirección. Compare con crypto.timingSafeEqual después de comprobar las longitudes. Este ejemplo Node.js usa Request/Headers y un Buffer que contiene el cuerpo original:
import { createHmac, timingSafeEqual } from "node:crypto";
export function verificarWebhook(headers, corpoBruto, segredo) {
const timestamp = headers.get("x-ativa-timestamp") ?? "";
const assinatura = headers.get("x-ativa-assinatura") ?? "";
if (!/^\d{1,12}$/.test(timestamp)) return false;
const agora = Math.floor(Date.now() / 1000);
if (Math.abs(agora - Number(timestamp)) > 300) return false;
if (!/^[0-9a-f]{64}$/.test(assinatura)) return false;
const esperada = createHmac("sha256", segredo)
.update(timestamp + ".", "utf8")
.update(corpoBruto)
.digest();
const recebida = Buffer.from(assinatura, "hex");
return recebida.length === esperada.length
&& timingSafeEqual(recebida, esperada);
}
export async function lerAviso(request, segredo) {
const corpoBruto = Buffer.from(await request.arrayBuffer());
if (!verificarWebhook(request.headers, corpoBruto, segredo)) {
throw new Error("assinatura_invalida");
}
return JSON.parse(corpoBruto.toString("utf8"));
}
Tras verificar, elimine duplicados por el id de la notificación en almacenamiento persistente y registre la recepción antes de procesar de forma asíncrona. Devuelva 2xx rápidamente, también para duplicados ya aceptados. El tiempo de espera de entrega es 5 s. No se garantiza una entrega exactamente una vez: una respuesta perdida puede provocar una repetición.
Hasta 8 intentos en total. Tras los fallos 1–7, las esperas son 1, 2, 4, 8, 16, 32 y 64 min, medidas desde la finalización del intento; las entregas se comprueban cada minuto. Solo HTTP 2xx confirma la entrega; 3xx, otros errores y tiempos de espera agotados provocan reintentos. Tras el octavo fallo no hay reenvío automático. El id y el cuerpo permanecen iguales entre intentos; se renuevan la marca de tiempo y la firma. Consulte GET /numeros/{id} si falta una notificación.
10. Modo de prueba
Cree una clave ativa_test_ en el dashboard y use los mismos endpoints y URL base. No se cobran fondos reales. El saldo ficticio inicial es R$ 100.00 (10000 céntimos BRL), independientemente de la moneda real de su cuenta. La opción es op_000000000001: precio ficticio R$ 0.83, referencia del sitio web R$ 1.20, duración de 20 min y cancelación después de 2 min.
Los teléfonos son números ficticios del rango +1 202 555-01xx, devueltos sin espacios, como +12025550123; el país elegido permanece en pais. El código 123456 está disponible después de 20 s; consultar el número después actualiza su estado, mientras que el webhook puede llegar en el minuto siguiente.
Use servico=teste_falha para no recibir código y probar la cancelación, sustitución (después de 2 min) o caducidad (después de 20 min), con reembolso ficticio. Los demás servicios reciben el código antes de que termine la espera de cancelación. Los números de prueba con código pasan a concluido al caducar.
Reinicie el saldo a R$ 100.00 en el dashboard: se cancelan los números abiertos sin código; se completan los que tienen código. El reinicio conserva el historial, los intentos, la idempotencia y las claves; no reinicia los límites por minuto. Use una nueva Idempotency-Key para la siguiente compra. El historial de prueba se limpia después de 30 días.
Las claves live y test no se mezclan: números, saldos, extractos, contadores de uso e idempotencia están separados. Los límites configurados y bloqueos de cliente_ref se aplican en ambos modos. El ping del dashboard solo prueba la entrega; compre un número con una clave de prueba para ejercitar modo: "test".
11. Consejos de integración
- Reutilice Idempotency-Key tras fallos de red; compruebe el resultado antes de elegir una nueva clave.
- Consulte GET /numeros/{id} si falta un webhook y respete los límites de uso.
- Gestione preco_acima_do_maximo: muestre el precio actualizado y obtenga la decisión del cliente antes de otra compra.
- Mantenga privado su precio de adquisición (preco_centavos); proteja también sus claves y el secreto del webhook.
- Envíe solo un cliente_ref anónimo; mantenga la relación con su cliente en su propio sistema.
Lea los Términos de reventa. Contacto: contato@ativasms.store.