# Documentação da aut2fa URL: https://doc.aut2fa.com/ Envie um código de uso único, acompanhe a entrega e valide o código informado pela pessoa. A integração acontece no seu servidor, pela API HTTP v1. Fazer a primeira integraçãoConsultar a API ## Um envio, três operações Enviar o códigoPOST /v1/sendReceba o ID do envio e o prazo de validade. A resposta 202 confirma que o pedido foi aceito. Acompanhar a entregaGET /v1/send/{id}/statusConsulte o estado da mensagem e os timestamps disponíveis. Verificar o códigoPOST /v1/send/{id}/verifyConclua a autenticação somente quando a resposta tiver valid: true. ## Faça um envio de teste Crie uma aplicação no painel da aut2fa em modo test e guarde a chave em uma variável de ambiente no servidor. O modo de teste usa 000000 quando você omite o código. cURLJavaScriptPythonPHP Copiar curl https://api.aut2fa.com/v1/send \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"+5531999999999","locale":"pt-BR"}' // Execute no servidor (Node.js 22+). const idempotencyKey = crypto.randomUUID(); const body = JSON.stringify({ to: "+5531999999999", locale: "pt-BR" }); // Guarde idempotencyKey e body antes de chamar; reutilize-os ao retentar. const response = await fetch("https://api.aut2fa.com/v1/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.AUT2FA_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": idempotencyKey, }, body, signal: AbortSignal.timeout(15000), }); const result = await response.json(); if (!response.ok) throw new Error(result.code); // Guarde result.id na sessão de autenticação do seu servidor. import json import os import urllib.request import uuid idempotency_key = str(uuid.uuid4()) body = json.dumps({"to": "+5531999999999", "locale": "pt-BR"}).encode("utf-8") # Guarde idempotency_key e body antes de chamar; reutilize-os ao retentar. request = urllib.request.Request( "https://api.aut2fa.com/v1/send", data=body, headers={ "Authorization": "Bearer " + os.environ["AUT2FA_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": idempotency_key, }, method="POST", ) with urllib.request.urlopen(request, timeout=15) as response: result = json.load(response) # Guarde result["id"] na sessão de autenticação do servidor. '+5531999999999', 'locale' => 'pt-BR', ], JSON_THROW_ON_ERROR); // Guarde a chave e $requestBody antes de chamar; reutilize-os ao retentar. $request = curl_init('https://api.aut2fa.com/v1/send'); curl_setopt_array($request, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AUT2FA_API_KEY'), 'Content-Type: application/json', 'Idempotency-Key: ' . $idempotencyKey, ], CURLOPT_POSTFIELDS => $requestBody, ]); $body = curl_exec($request); if ($body === false) throw new RuntimeException(curl_error($request)); $status = curl_getinfo($request, CURLINFO_HTTP_CODE); curl_close($request); $result = json_decode($body, true, 512, JSON_THROW_ON_ERROR); if ($status !== 202) throw new RuntimeException($result['code'] ?? 'http_error'); // Guarde $result['id'] na sessão de autenticação do servidor. Os exemplos nativos geram uma chave única por pedido. Guarde a chave e o corpo antes da chamada para reutilizá-los nas retentativas. O cURL mínimo não usa idempotência; veja como habilitá-la antes de retentar. O início rápido mostra como guardar o ID e verificar esse envio. ## Disponibilidade atual RecursoComportamento atual WhatsAppEntrega real para telefones válidos no modo live. Modo testSimula os estados de entrega sem enviar mensagem nem consumir créditos. E-mailO envio público retorna channel_unavailable. SMS e TelegramAinda não estão disponíveis no fluxo público de OTP. O cliente informa o destinatário; a plataforma escolhe o canal e o remetente. Veja como acompanhar a entrega. ## Referências para a integração Chaves e autenticaçãoUse a chave no servidor e identifique o modo da aplicação. IdempotênciaRepita uma requisição sem criar outro envio. Erros e recuperaçãoTrate o código do erro e escolha a próxima ação. OpenAPI 3.1Importe o contrato em clientes HTTP e ferramentas. # Início rápido URL: https://doc.aut2fa.com/quickstart Este fluxo usa uma aplicação de teste. Você pode implementar a autenticação completa sem entregar mensagens ou consumir créditos. ## 1. Crie uma aplicação de teste No painel, crie uma aplicação em modo test. Guarde a chave ak_test_… em AUT2FA_API_KEY no servidor. Os exemplos de terminal usam Bash. Substitua o valor abaixo pela chave da sua aplicação: BashCopiar export AUT2FA_API_KEY='ak_test_SUA_CHAVE' A chave fica no servidorChame a API pelo seu backend. Expor a chave no navegador, em um aplicativo distribuído ou em um repositório permite que outras pessoas usem sua conta. Use a URL base https://api.aut2fa.com e o cabeçalho Authorization: Bearer SUA_CHAVE. ## 2. Solicite o código Use um telefone válido em formato internacional, iniciado por +. O exemplo omite code e cria o código de teste 000000. cURLJavaScriptPythonPHP Copiar curl https://api.aut2fa.com/v1/send \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"+5531999999999","locale":"pt-BR"}' // Execute no servidor (Node.js 22+). const idempotencyKey = crypto.randomUUID(); const body = JSON.stringify({ to: "+5531999999999", locale: "pt-BR" }); // Guarde idempotencyKey e body antes de chamar; reutilize-os ao retentar. const response = await fetch("https://api.aut2fa.com/v1/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.AUT2FA_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": idempotencyKey, }, body, signal: AbortSignal.timeout(15000), }); const result = await response.json(); if (!response.ok) throw new Error(result.code); // Guarde result.id na sessão de autenticação do seu servidor. import json import os import urllib.request import uuid idempotency_key = str(uuid.uuid4()) body = json.dumps({"to": "+5531999999999", "locale": "pt-BR"}).encode("utf-8") # Guarde idempotency_key e body antes de chamar; reutilize-os ao retentar. request = urllib.request.Request( "https://api.aut2fa.com/v1/send", data=body, headers={ "Authorization": "Bearer " + os.environ["AUT2FA_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": idempotency_key, }, method="POST", ) with urllib.request.urlopen(request, timeout=15) as response: result = json.load(response) # Guarde result["id"] na sessão de autenticação do servidor. '+5531999999999', 'locale' => 'pt-BR', ], JSON_THROW_ON_ERROR); // Guarde a chave e $requestBody antes de chamar; reutilize-os ao retentar. $request = curl_init('https://api.aut2fa.com/v1/send'); curl_setopt_array($request, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AUT2FA_API_KEY'), 'Content-Type: application/json', 'Idempotency-Key: ' . $idempotencyKey, ], CURLOPT_POSTFIELDS => $requestBody, ]); $body = curl_exec($request); if ($body === false) throw new RuntimeException(curl_error($request)); $status = curl_getinfo($request, CURLINFO_HTTP_CODE); curl_close($request); $result = json_decode($body, true, 512, JSON_THROW_ON_ERROR); if ($status !== 202) throw new RuntimeException($result['code'] ?? 'http_error'); // Guarde $result['id'] na sessão de autenticação do servidor. Nos clientes nativos, guarde a chave única e o corpo serializado antes da chamada. Cada novo pedido gera outra chave; uma retentativa reutiliza a chave e o corpo originais. O cURL mínimo omite o cabeçalho opcional: para retentar com segurança, consulte idempotência. Resposta 202 Accepted: JSONCopiar { "id": "snd_01m4prwckhd0kyjgv5vw8a5wjr", "status": "queued", "verification": "pending", "mode": "test", "channel": null, "from": null, "expires_at": "2026-10-11T15:10:00Z", "created_at": "2026-10-11T15:00:00Z", "sent_at": null, "delivered_at": null, "read_at": null, "verified_at": null, "failed_at": null, "failure_reason": null } Guarde id e expires_at na sessão de autenticação do servidor, vinculados à pessoa e à operação que iniciou o pedido. A API não devolve o código. ## 3. Verifique o código Use o id recebido na etapa anterior como SEND_ID e envie o código informado pela pessoa como string. Neste teste, ele é 000000. cURLCopiar curl "https://api.aut2fa.com/v1/send/$SEND_ID/verify" \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"code":"000000"}' Resposta 200 OK ao acertar: JSONCopiar { "valid": true, "verification": "verified", "attempts_left": 0 } Conclua a autenticação apenas se valid === true. Um HTTP 200 também pode conter código incorreto, expirado, bloqueado ou já utilizado. O código é aceito uma única vez. Após o sucesso, attempts_left é 0; isso indica que a verificação encerrou. Veja todos os resultados em verificar código. ## 4. Prepare o modo live Crie uma aplicação live e configure a chave ak_live_… no seu servidor. O modo é definido pela aplicação da chave; não existe parâmetro mode no corpo do envio. Confirme a cota e o saldo antes de enviar. Leia idempotência para retentar após uma falha de rede. Trate limites e Retry-After no fluxo de reenvio. Acompanhe o status quando precisar informar uma falha de entrega. # Autenticação URL: https://doc.aut2fa.com/authentication Os endpoints de envio usam uma chave de aplicação como Bearer token. A chave identifica a aplicação, a conta e o modo de execução. ## Cabeçalho da requisição HTTPCopiar Authorization: Bearer ak_test_SUA_CHAVE Crie a aplicação no painel e salve a chave em uma variável de ambiente. Envie o cabeçalho em todas as chamadas a /v1/send, status e verificação. Use HTTPS. Não registre o cabeçalho de autenticação em logs nem inclua a chave em URLs. ## Chaves de teste e de produção ChaveModoEfeito ak_test_…testCria envios gratuitos e simula a entrega. ak_live_…liveCria envios reais e reserva uma unidade da cota ou um crédito. Use credenciais próprias para cada aplicação e ambiente. A idempotência pertence à aplicação; consultar e verificar um envio usa o escopo da conta autenticada. ## Proteja a integração Faça as chamadas à aut2fa no seu servidor. Vincule o ID do envio à sessão e à pessoa que pediu a autenticação. Valide a sessão antes de aceitar pedidos de envio, reenvio ou verificação. Se uma chave vazar, revogue-a no painel, crie outra e atualize a configuração do servidor. Não aceite um ID arbitrário vindo do navegador como prova de que um envio pertence à sessão atual. ## Falhas de autenticação HTTPCódigoPróxima ação 401missing_credentialsEnvie Authorization com Bearer e a chave. 401invalid_api_keyConfira a credencial, sua configuração e se foi revogada. GET /v1/signup-settings é público e não exige esse cabeçalho. Ele informa a cota vigente para novos cadastros; veja cota de cadastro. # Modo de teste URL: https://doc.aut2fa.com/test-mode Uma aplicação test executa o mesmo contrato HTTP usado no modo live, com entrega simulada. O modo vem da chave da aplicação. ## Código de teste Corpo do envioCódigo para verificar code omitido ou vazio000000 "code": "1234"1234 Código próprio também vale em test: informe de 4 a 10 dígitos como string. Não substitua um código próprio por 000000 ao verificar. JSONCopiar {"to":"+5531999999999","code":"1234","locale":"pt-BR"} O código não aparece nas respostas de envio ou status, mesmo no modo de teste. ## Entrega simulada O envio começa como queued. Quando o processamento de teste termina, o status fica read, o canal fica sandbox e sent_at, delivered_at e read_at recebem timestamps. Nenhuma mensagem chega ao telefone. A verificação continua independente: uma entrega simulada pode ter verification: pending. Use um telefone válidoO modo test mantém a validação do destinatário. E-mail válido continua retornando channel_unavailable; test não habilita um canal indisponível. ## Cenários para validar Acerto na primeira tentativa: valid: true, verification: verified, attempts_left: 0. Código incorreto: HTTP 200, valid: false, uma tentativa a menos. Cinco erros: verification: locked. Após expires_at: verification: expired. Verificar novamente após o sucesso: valid: false e verification: verified. Repetir o corpo e a chave de idempotência: o mesmo ID de envio. Envios test não consomem a cota grátis nem créditos. Os limites de requisição continuam aplicáveis. # Enviar código URL: https://doc.aut2fa.com/api/send POST/v1/sendCopiar Cria um envio para processamento assíncrono. A resposta 202 Accepted confirma o aceite do pedido; consulte o status para acompanhar a entrega. ## Requisição Use Authorization: Bearer SUA_CHAVE e Content-Type: application/json. O cabeçalho opcional Idempotency-Key evita duplicações em retentativas. CampoTipoRegra tostring, obrigatórioTelefone válido em formato internacional E.164, iniciado por +. Exemplo: +5531999999999. codestring, opcionalDe 4 a 10 dígitos. Quando omitido, a aut2fa gera 6 dígitos em live ou usa 000000 em test. localestring, opcionalUse pt-BR ou en. Quando omitido, usa o idioma da conta. Preserve zeros iniciais: envie "0042", não um número. O telefone é normalizado; números sem o sinal + e código do país são rejeitados. O canal é escolhido pela plataformaNão envie channel ou from. O fluxo público entrega por WhatsApp atualmente. Um e-mail válido retorna channel_unavailable. cURLJavaScriptPythonPHP Copiar curl https://api.aut2fa.com/v1/send \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"+5531999999999","locale":"pt-BR"}' // Execute no servidor (Node.js 22+). const idempotencyKey = crypto.randomUUID(); const body = JSON.stringify({ to: "+5531999999999", locale: "pt-BR" }); // Guarde idempotencyKey e body antes de chamar; reutilize-os ao retentar. const response = await fetch("https://api.aut2fa.com/v1/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.AUT2FA_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": idempotencyKey, }, body, signal: AbortSignal.timeout(15000), }); const result = await response.json(); if (!response.ok) throw new Error(result.code); // Guarde result.id na sessão de autenticação do seu servidor. import json import os import urllib.request import uuid idempotency_key = str(uuid.uuid4()) body = json.dumps({"to": "+5531999999999", "locale": "pt-BR"}).encode("utf-8") # Guarde idempotency_key e body antes de chamar; reutilize-os ao retentar. request = urllib.request.Request( "https://api.aut2fa.com/v1/send", data=body, headers={ "Authorization": "Bearer " + os.environ["AUT2FA_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": idempotency_key, }, method="POST", ) with urllib.request.urlopen(request, timeout=15) as response: result = json.load(response) # Guarde result["id"] na sessão de autenticação do servidor. '+5531999999999', 'locale' => 'pt-BR', ], JSON_THROW_ON_ERROR); // Guarde a chave e $requestBody antes de chamar; reutilize-os ao retentar. $request = curl_init('https://api.aut2fa.com/v1/send'); curl_setopt_array($request, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AUT2FA_API_KEY'), 'Content-Type: application/json', 'Idempotency-Key: ' . $idempotencyKey, ], CURLOPT_POSTFIELDS => $requestBody, ]); $body = curl_exec($request); if ($body === false) throw new RuntimeException(curl_error($request)); $status = curl_getinfo($request, CURLINFO_HTTP_CODE); curl_close($request); $result = json_decode($body, true, 512, JSON_THROW_ON_ERROR); if ($status !== 202) throw new RuntimeException($result['code'] ?? 'http_error'); // Guarde $result['id'] na sessão de autenticação do servidor. Os clientes nativos geram uma chave única por novo pedido. Antes da chamada, guarde essa chave e o corpo serializado para reutilizá-los em uma retentativa. O cURL mínimo omite idempotência; consulte idempotência para repetir chamadas com segurança. ## Resposta 202 JSONCopiar { "id": "snd_01m4prwckhd0kyjgv5vw8a5wjr", "status": "queued", "verification": "pending", "mode": "test", "channel": null, "from": null, "expires_at": "2026-10-11T15:10:00Z", "created_at": "2026-10-11T15:00:00Z", "sent_at": null, "delivered_at": null, "read_at": null, "verified_at": null, "failed_at": null, "failure_reason": null } Este exemplo usa uma chave test. Em uma aplicação live, mode será live. Uma retentativa idempotente pode retornar o estado atual de um envio já existente. A resposta nunca contém o código OTP. Guarde o id no servidor para consultar e verificar o envio. CampoTipoSignificado idstringIdentificador do envio; use em status e verificação. statusstringEstado da entrega. Veja os estados de entrega. verificationstringpending, verified, expired ou locked; separado do estado da entrega. modestringtest ou live, conforme a aplicação da chave. channelstring ou nullCanal escolhido pela plataforma. null antes do roteamento; sandbox em teste. fromstring ou nullRemetente usado, quando definido. expires_atdata e horaPrazo de validade do código. Compare com o horário atual. created_atdata e horaQuando o envio foi criado. sent_atdata e hora ou nullQuando o provedor aceitou a mensagem. delivered_atdata e hora ou nullQuando a entrega foi confirmada, se houver recibo. read_atdata e hora ou nullQuando a leitura foi confirmada, se houver recibo. verified_atdata e hora ou nullQuando o código foi verificado com sucesso. failed_atdata e hora ou nullQuando a entrega encerrou com falha. failure_reasonstring ou nullMotivo da falha de entrega. Veja falhas de entrega. Datas usam o formato RFC 3339. null indica que a informação ainda não existe ou não está disponível; trate isso antes de formatar uma data. ## Validação e erros HTTPCódigos principais 401missing_credentials, invalid_api_key 402insufficient_credits 409idempotency_key_reused 422invalid_json, invalid_recipient, invalid_code, invalid_locale, invalid_idempotency_key, channel_unavailable 429rate_limited, com Retry-After Veja o envelope de erro para tratar a resposta pelo campo code. Após uma falha de rede, repita os mesmos bytes do corpo e a mesma chave de idempotência. # Consultar status URL: https://doc.aut2fa.com/api/status GET/v1/send/{id}/statusCopiar Retorna o envio da conta autenticada, com os estados de entrega e verificação. Use o ID recebido ao criar o envio. ## Requisição Substitua SEND_ID pelo ID guardado no seu servidor. Envie a chave no cabeçalho Authorization. cURLCopiar curl "https://api.aut2fa.com/v1/send/$SEND_ID/status" \ -H "Authorization: Bearer $AUT2FA_API_KEY" ## Resposta 200 JSONCopiar { "id": "snd_01m4prwckhd0kyjgv5vw8a5wjr", "status": "read", "verification": "pending", "mode": "test", "channel": "sandbox", "from": null, "expires_at": "2026-10-11T15:10:00Z", "created_at": "2026-10-11T15:00:00Z", "sent_at": "2026-10-11T15:00:01Z", "delivered_at": "2026-10-11T15:00:01Z", "read_at": "2026-10-11T15:00:01Z", "verified_at": null, "failed_at": null, "failure_reason": null } O formato é o mesmo da resposta de envio. O exemplo representa uma entrega simulada concluída, com o código ainda pendente de verificação. status: read não autentica a pessoa. Para isso, chame verificar código e confira valid. ## Como acompanhar Se precisar atualizar a interface, consulte com um intervalo moderado e encerre a consulta quando houver o estado desejado, uma falha ou o fim do prazo. A API pública não define um intervalo obrigatório de polling. Os recibos dependem do provedor. Um envio pode permanecer em sent sem receber confirmação de entrega ou leitura. Trate os timestamps como anuláveis. Quando um código pendente atinge expires_at, a consulta retorna verification: expired. O status da entrega pode continuar sent, delivered ou read. ## Erros Um ID inexistente ou fora da conta autenticada retorna 404 com send_not_found. Credenciais ausentes ou inválidas retornam 401. Para diagnosticar uma mensagem que falhou, consulte failure_reason e leia falhas de entrega. # Verificar código URL: https://doc.aut2fa.com/api/verify POST/v1/send/{id}/verifyCopiar Compara o código informado com o código do envio. O resultado de autenticação está em valid, não no status HTTP. ## Requisição Envie Authorization, Content-Type e um objeto JSON com code como string. No modo live, use o código recebido pela pessoa. O exemplo usa o código padrão de teste. cURLCopiar curl "https://api.aut2fa.com/v1/send/$SEND_ID/verify" \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"code":"000000"}' Vincule o ID à sessão atual antes de fazer a chamada. O estado de entrega não é uma condição para chamar a verificação. ## Resposta 200: código correto JSONCopiar { "valid": true, "verification": "verified", "attempts_left": 0 } CampoSignificado validtrue somente na chamada que verifica o código com sucesso. verificationEstado após a chamada: pending, verified, expired ou locked. attempts_leftTentativas restantes depois de um erro. É 0 quando a verificação encerrou, inclusive no sucesso. Conclua a operação protegida somente quando valid === true. O código é de uso único: repetir uma verificação bem-sucedida retorna valid: false e verification: verified. ## Código incorreto e estados encerrados Situaçãovalidverificationattempts_left Primeiro erro, antes de expirarfalsepending4 Quinto errofalselocked0 Prazo encerradofalseexpired0 Código já usadofalseverified0 Todos esses resultados retornam HTTP 200. Cinco códigos incorretos bloqueiam o envio. Se o estado for expired ou locked, ofereça um novo envio com outro ID e outra chave de idempotência. Retentativas de verificaçãoA verificação não usa Idempotency-Key. Se a resposta de sucesso se perder na rede, uma repetição pode retornar valid: false e verification: verified. Esse estado informa que houve uma verificação anterior; sozinho, não autoriza concluir a sessão. Evite retentativas automáticas da verificação. Se o resultado ficar indeterminado após timeout ou erro de rede, consulte o status para diagnosticar. Retome a autenticação somente se o seu próprio backend já registrou valid: true para essa sessão; se não conseguir recuperar esse resultado, inicie outro desafio com novo ID e outra chave de idempotência. ## Prazo de validade O prazo padrão da configuração é 10 minutos, mas pode mudar. Sempre use o expires_at do envio, em vez de fixar uma duração na integração. Um envio verificado permanece verified após o prazo; apenas códigos ainda pendentes passam a expired. ## Erros HTTP Corpo JSON inválido retorna 422 com invalid_json. Código incorreto retorna o resultado HTTP 200 descrito acima. ID inexistente ou de outra conta retorna 404 com send_not_found. Chave ausente ou inválida retorna 401. # Idempotência URL: https://doc.aut2fa.com/idempotency Use Idempotency-Key ao criar um envio. Se a conexão falhar depois do aceite, você poderá recuperar o mesmo envio ao repetir a requisição. ## Uma chave por intenção de envio Gere uma chave para cada novo pedido de código, guarde-a com o corpo serializado e reutilize ambos nas retentativas desse pedido. HTTPCopiar Idempotency-Key: login-unique-attempt-001 A chave é opcional, pertence à aplicação e tem no máximo 255 bytes após remover espaços nas extremidades. Uma chave vazia equivale a não usar idempotência. Prefira ASCII, como um UUID. Duas aplicações podem usar a mesma chave sem compartilhar o envio. Na mesma aplicação, a mesma chave e o mesmo corpo retornam o mesmo id, sem reservar outra unidade nem consumir novamente o limite de criação. ## O corpo precisa ser idêntico A API calcula o hash dos bytes exatos recebidos. JSON com os mesmos valores pode ter outro hash se você mudar espaços, ordem dos campos ou a representação do texto. Corpo originalCopiar {"to":"+5531999999999","locale":"pt-BR"} Outro corpo: retorna 409 com a mesma chaveCopiar { "locale": "pt-BR", "to": "+5531999999999" } Serialize o corpo uma vez e reutilize a string ou o buffer. Em clientes Python, PHP e JavaScript, não reconstrua o objeto com outra ordem de campos ao retentar. ## Retentativa no servidor JavaScriptCopiar const key = crypto.randomUUID(); const body = JSON.stringify({ to: "+5531999999999", locale: "pt-BR" }); async function requestSend() { return fetch("https://api.aut2fa.com/v1/send", { method: "POST", headers: { Authorization: "Bearer " + process.env.AUT2FA_API_KEY, "Content-Type": "application/json", "Idempotency-Key": key, }, body, }); } // Guarde key e body para repetir este pedido após uma falha de rede. const response = await requestSend(); Uma resposta HTTP recebida deve ser tratada antes da retentativa. Em 429, respeite Retry-After. Em falha temporária de rede ou servidor, repita com intervalo crescente e um número limitado de tentativas. ## Conflito e reenvio 409 com idempotency_key_reused significa que a chave já existe com outro corpo. Recupere o corpo original para retentar a mesma operação. Para um novo pedido de código, inclusive depois de expiração ou bloqueio, gere outra chave. Reutilizar a chave antiga recupera o envio antigo, sem renovar o prazo ou reiniciar tentativas. O cabeçalho vale para POST /v1/send. A verificação é de uso único e não implementa essa idempotência. # Entrega e estados URL: https://doc.aut2fa.com/delivery Uma resposta 202 registra o envio na fila. O processamento escolhe o remetente, envia a mensagem e atualiza os estados conforme os recibos disponíveis. ## Canais disponíveis CanalDisponibilidade na API pública WhatsAppEntrega real em live, usando remetentes disponíveis da plataforma. SandboxSimulação em test, sem mensagem real. E-mail422 channel_unavailable, mesmo com um endereço válido. SMSAinda não disponível no fluxo público de OTP. TelegramAinda não disponível no fluxo público de OTP. Ter SMTP ou testes de SMS configuráveis no painel não habilita esses canais em POST /v1/send. O cliente não escolhe o canal com um campo no corpo. ## Estados de entrega: status EstadoSignificado queuedEnvio aceito; aguardando processamento ou um remetente disponível. sendingEnvio roteado para uma tentativa de entrega. sentO provedor aceitou a mensagem. Ainda não confirma que chegou ao telefone. deliveredO provedor confirmou a entrega. readO provedor confirmou a leitura. failedA entrega encerrou com falha. Consulte failure_reason. Recibos podem chegar com atraso ou não chegar. Um envio pode permanecer em sent, e nem toda integração verá todos os estados intermediários. Em teste, o processamento simula sent, delivered e read de uma vez, com channel: sandbox. ## Estados do código: verification EstadoSignificado pendingCódigo ainda pode ser verificado dentro do prazo. verifiedO código já foi usado com sucesso. expiredO prazo de um código pendente encerrou. lockedCinco verificações incorretas bloquearam o envio. A entrega e a verificação são independentes. Uma mensagem lida pode estar pendente, e uma mensagem entregue pode ter um código expirado. Use valid: true na verificação para autenticar. ## Falhas de entrega failure_reasonSignificado expired_before_deliveryO código expirou antes de a entrega terminar. attempts_exhaustedO processamento esgotou as tentativas de entrega. rejected_by_providerO provedor rejeitou a mensagem. Enquanto não houver remetente disponível, o envio pode continuar queued até expirar. O processamento faz as retentativas de entrega; não crie envios repetidos a cada consulta de status. Quando a entrega falha de forma definitiva, a plataforma devolve a unidade reservada da cota grátis ou o crédito. Veja reserva e devolução. # Limites e reenvio URL: https://doc.aut2fa.com/limits Os limites protegem a criação de envios e o uso de códigos. Respeite o retorno da API e dê uma próxima ação clara no seu fluxo. ## Limites de criação POST /v1/send tem um limite da plataforma por conta. A configuração padrão é 600 envios por minuto; a operação pode alterar esse valor. A aplicação também pode ter limites por minuto e por destinatário por hora, configurados no painel. Eles vêm desativados por padrão; os valores iniciais, quando habilitados, são 60 por minuto e 5 por destinatário por hora. Esses limites também se aplicam ao modo test. Recuperar um envio existente com idempotência não consome novamente o limite de criação. ## HTTP 429 e Retry-After HTTPCopiar HTTP/1.1 429 Too Many Requests Content-Type: application/problem+json Retry-After: 37 O código do erro é rate_limited. Retry-After informa quantos segundos aguardar antes da próxima tentativa. Apresente esse prazo no botão de reenvio e impeça chamadas repetidas enquanto ele não termina. Se retentar o mesmo pedido, preserve a chave de idempotência e os bytes do corpo. ## Tentativas e validade do código Cinco verificações incorretas bloqueiam o envio. Use attempts_left para informar quantas tentativas restam depois de um erro; no sucesso, ele também é zero. O prazo padrão é 10 minutos, configurável na operação. Use expires_at retornado pela API. Reenvio cria outro código, com outro ID e outra chave de idempotência. O endpoint de verificação não recebe um parâmetro para aumentar tentativas ou estender o prazo. ## Limites de formato DadoLimite Corpo JSON64 KiB por requisição. Idempotency-Key255 bytes após trim. Código próprio no envioDe 4 a 10 dígitos, como string. Idioma canônicopt-BR ou en. DestinatárioTelefone válido com + e código do país. Formato inválido retorna 422. Corrija o corpo antes de repetir a chamada; uma retentativa sem alteração não resolve um erro de validação. # Cota e créditos URL: https://doc.aut2fa.com/credits Um envio live reserva uma unidade da cota grátis ou um crédito. Envios test são gratuitos e não reduzem esses saldos. ## Reserva e devolução A plataforma usa primeiro uma unidade da cota grátis, se houver. Quando a cota acaba, reserva um crédito por envio live aceito. Se não há cota nem crédito, responde 402 insufficient_credits. Quando a entrega encerra com falha, devolve a unidade da origem da reserva. O crédito é reservado ao criar o envio, antes da entrega. Código incorreto, bloqueio de verificação ou expiração após a mensagem ter sido enviada não são, por si só, falhas de entrega. Repetir o pedido com a mesma chave e o mesmo corpo não cobra novamente. Acompanhe os saldos e o extrato no painel. ## Cota vigente para novos cadastros GET/v1/signup-settingsCopiar Este endpoint é público, sem Authorization. Ele informa a configuração para novos cadastros, não o saldo de uma conta existente. cURLCopiar curl https://api.aut2fa.com/v1/signup-settings Resposta 200 OK: JSONCopiar {"free_sends":10} O padrão atual é 10 envios grátis, mas o valor é configurável. Consulte free_sends quando precisar exibir a oferta vigente; não fixe esse número no seu produto. A resposta usa Cache-Control: no-store. Alterações da configuração valem para novos cadastros e não redefinem o saldo das contas existentes. ## Saldo insuficiente Trate insufficient_credits como uma condição da conta. Verifique o saldo no painel e regularize-o antes de repetir. A compra automática de créditos ainda não está disponível. Solicite o ajuste de créditos à equipe administradora e confira as condições na página de preços. Evite retentativas automáticas contínuas para esse erro. A integração não recebe um endpoint público de recarga no contrato apresentado aqui. # Clientes HTTP URL: https://doc.aut2fa.com/integrations A API usa HTTPS e JSON. Os exemplos usam clientes HTTP da linguagem, sem depender de um pacote de SDK da aut2fa. ## Escolha o cliente do servidor AmbienteCliente usado Node.js 22 ou superiorfetch nativo. Python 3urllib.request da biblioteca padrão. PHPExtensão cURL e json_encode. Terminalcurl. cURLJavaScriptPythonPHP Copiar curl https://api.aut2fa.com/v1/send \ -H "Authorization: Bearer $AUT2FA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"+5531999999999","locale":"pt-BR"}' // Execute no servidor (Node.js 22+). const idempotencyKey = crypto.randomUUID(); const body = JSON.stringify({ to: "+5531999999999", locale: "pt-BR" }); // Guarde idempotencyKey e body antes de chamar; reutilize-os ao retentar. const response = await fetch("https://api.aut2fa.com/v1/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.AUT2FA_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": idempotencyKey, }, body, signal: AbortSignal.timeout(15000), }); const result = await response.json(); if (!response.ok) throw new Error(result.code); // Guarde result.id na sessão de autenticação do seu servidor. import json import os import urllib.request import uuid idempotency_key = str(uuid.uuid4()) body = json.dumps({"to": "+5531999999999", "locale": "pt-BR"}).encode("utf-8") # Guarde idempotency_key e body antes de chamar; reutilize-os ao retentar. request = urllib.request.Request( "https://api.aut2fa.com/v1/send", data=body, headers={ "Authorization": "Bearer " + os.environ["AUT2FA_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": idempotency_key, }, method="POST", ) with urllib.request.urlopen(request, timeout=15) as response: result = json.load(response) # Guarde result["id"] na sessão de autenticação do servidor. '+5531999999999', 'locale' => 'pt-BR', ], JSON_THROW_ON_ERROR); // Guarde a chave e $requestBody antes de chamar; reutilize-os ao retentar. $request = curl_init('https://api.aut2fa.com/v1/send'); curl_setopt_array($request, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('AUT2FA_API_KEY'), 'Content-Type: application/json', 'Idempotency-Key: ' . $idempotencyKey, ], CURLOPT_POSTFIELDS => $requestBody, ]); $body = curl_exec($request); if ($body === false) throw new RuntimeException(curl_error($request)); $status = curl_getinfo($request, CURLINFO_HTTP_CODE); curl_close($request); $result = json_decode($body, true, 512, JSON_THROW_ON_ERROR); if ($status !== 202) throw new RuntimeException($result['code'] ?? 'http_error'); // Guarde $result['id'] na sessão de autenticação do servidor. Para executar o JavaScript no Node.js, salve o exemplo em enviar.mjs e rode node enviar.mjs. A extensão .mjs permite o await no nível principal. Os comandos cURL usam Bash, com AUT2FA_API_KEY no ambiente. Guarde a chave gerada e os bytes do corpo antes da chamada. Execute a geração novamente só para um novo pedido de código. Uma retentativa reutiliza os valores guardados; trocar a linguagem do exemplo não garante os mesmos bytes de JSON. Configure um timeout adequado ao seu fluxo. Uma falha de rede não indica que a API deixou de criar o envio; retente usando idempotência. ## Fluxo de autenticação no servidor Receba o telefone e valide a sessão que pediu a operação. Crie o envio e guarde ID, prazo, chave de idempotência e corpo nessa sessão. Receba o código como string e recupere o ID guardado no servidor. Chame a verificação e conclua a operação somente com valid: true. Encerre a sessão de desafio depois do sucesso. O navegador não decide o resultadoA interface pode exibir os estados, mas a autorização da operação protegida depende da resposta valid no seu servidor. ## Trate HTTP e resultado separadamente JavaScriptCopiar async function verifySend(sendId, code) { const response = await fetch( "https://api.aut2fa.com/v1/send/" + encodeURIComponent(sendId) + "/verify", { method: "POST", headers: { Authorization: "Bearer " + process.env.AUT2FA_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ code }), signal: AbortSignal.timeout(15000), }, ); const result = await response.json(); if (!response.ok) { throw new Error(result.code ?? "http_error"); } return result; } // Recupere o sendId da sessão do servidor antes desta chamada. // Autorize a operação apenas quando result.valid === true. Uma verificação incorreta retorna HTTP 200 e valid: false. Para erros HTTP, leia o campo code do envelope application/problem+json. Em Python, urllib.request.urlopen lança urllib.error.HTTPError para erros HTTP; leia o corpo desse erro para obter code. Em PHP, verifique o status retornado por CURLINFO_HTTP_CODE. # Erros e recuperação URL: https://doc.aut2fa.com/errors Erros HTTP usam application/problem+json. Trate o campo code para decidir a próxima ação; title e detail são textos e podem mudar. ## Formato da resposta JSONCopiar { "type": "https://aut2fa.com/docs/errors#invalid_recipient", "title": "Unprocessable Entity", "status": 422, "code": "invalid_recipient", "detail": "\"to\" must be a phone number in international format (+5531999999999) or an e-mail address" } CampoPresençaUso typeSempreURL com a descrição do problema. titleSempreTítulo do status HTTP. statusSempreStatus HTTP como número. codeSempreCódigo estável para tratar na integração. detailOpcionalDescrição textual da condição. errorsOpcionalObjeto com erros por campo, quando houver. Não compare a mensagem em detail. Em 429, leia também Retry-After. Uma verificação com valid: false e HTTP 200 é um resultado de verificação; não usa este envelope. ## missing_credentials HTTP 401 A requisição não trouxe um Bearer token. Envie Authorization: Bearer SUA_CHAVE a partir do seu servidor. ## invalid_api_key HTTP 401 A chave não é válida ou foi revogada. Confira a variável de ambiente e a aplicação no painel. Substitua a credencial se ela foi revogada. ## invalid_recipient HTTP 422 O destinatário não passou pela validação de formato. Use um telefone válido com + e código do país, como +5531999999999. E-mail válido ainda não habilita entrega por e-mail. ## channel_unavailable HTTP 422 O destinatário é um e-mail, mas a entrega pública por e-mail ainda não está disponível. Informe um telefone válido. O fluxo público atual entrega por WhatsApp; configurar SMTP no painel não altera essa disponibilidade. ## invalid_code HTTP 422 O código próprio no pedido de envio não tem de 4 a 10 dígitos. Envie code como string de dígitos, preservando zeros iniciais, ou omita o campo para gerar um código. Esse erro pertence à criação: um código incorreto em verify retorna HTTP 200 com valid: false. ## invalid_locale HTTP 422 O idioma informado não é suportado. Use pt-BR ou en, ou omita locale para usar o idioma da conta. ## invalid_idempotency_key HTTP 422 A chave de idempotência ultrapassou 255 bytes após trim. Use uma chave ASCII de até 255 bytes, como um UUID. O limite é de bytes, não de caracteres Unicode. ## idempotency_key_reused HTTP 409 A chave já foi usada nessa aplicação com outro corpo de requisição. Para retentar o mesmo pedido, recupere os bytes originais do corpo. Para um novo pedido, gere outra chave. Espaços e ordem dos campos também alteram o hash. ## send_not_found HTTP 404 O ID não existe na conta autenticada. Use o ID retornado na criação e a chave da conta correta. Recupere o ID da sessão do servidor, em vez de aceitar um ID arbitrário da interface. ## insufficient_credits HTTP 402 A conta não tem cota grátis nem crédito disponível para um envio live. Confira o saldo no painel e regularize-o antes de retentar. O modo test não consome cota nem crédito. ## rate_limited HTTP 429 Um limite de criação por conta, aplicação ou destinatário foi atingido. Aguarde os segundos informados no cabeçalho Retry-After. Preserve a chave e o corpo nas retentativas do mesmo pedido. ## invalid_json HTTP 422 O corpo não pôde ser lido como o JSON esperado, ou excedeu o limite de 64 KiB. Envie um objeto JSON com os tipos corretos e Content-Type: application/json. Corrija o corpo antes de retentar. ## internal_error HTTP 500 A API não conseguiu devolver o resultado por um erro interno. Na criação do envio, retente com intervalo crescente e limite de tentativas, preservando a chave de idempotência e o corpo. Em verify, evite retentativas automáticas: o código pode já ter sido consumido. Consulte o status para diagnosticar, mas só retome a autenticação se seu próprio backend já registrou valid: true para essa sessão. Se o resultado continuar indeterminado, crie outro desafio. Veja verificação de uso único e recuperação. # Contrato OpenAPI URL: https://doc.aut2fa.com/openapi O contrato OpenAPI 3.1 descreve as operações públicas, seus campos e exemplos. Importe o JSON na sua ferramenta HTTP ou use-o para gerar um cliente. Baixar OpenAPI JSONAbrir contrato JSON ## Operações descritas MétodoCaminhoResposta de sucessoReferência POST/v1/send202Enviar código GET/v1/send/{id}/status200Consultar status POST/v1/send/{id}/verify200Verificar código GET/v1/signup-settings200Cota de cadastro A URL base é https://api.aut2fa.com. As operações de envio usam Bearer token; signup-settings é público. ## Ao importar o contrato Configure a chave no ambiente do servidor ou na variável secreta da sua ferramenta. Use um leitor compatível com OpenAPI 3.1 e tipos anuláveis do JSON Schema. Preserve os bytes serializados do corpo nas retentativas idempotentes. Trate os campos de data anuláveis antes de formatá-los. Confira valid na verificação, mesmo quando o HTTP for 200. Clientes gerados não alteram as regras do serviço. Veja clientes HTTP para exemplos com as bibliotecas nativas. ## Referência em texto llms.txt lista os guias e o contrato para ferramentas de leitura. llms-full.txt reúne o conteúdo da documentação em um único arquivo de texto. Esses arquivos descrevem a mesma API pública documentada neste site.