
A resposta curta: escreva uma só função que envia o SMS e use-a em todo o sistema. Ela recebe o número, o texto e uma chave do evento, lê a chave da API de uma variável de ambiente, tem tempo limite, envia sempre Idempotency-Key e devolve o código HTTP e a resposta. A decisão de repetir fica num só lugar: repete-se com espera num 429 ou 5xx, nunca num 422.
Em PHP
function enviar_sms($numero, $texto, $chave_evento) {
$ch = curl_init('https://api.mozout.com/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('SMS_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . $chave_evento,
],
CURLOPT_POSTFIELDS => json_encode(['number' => $numero, 'text' => $texto]),
]);
$corpo = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [$http, json_decode((string) $corpo, true)];
}
Em Python
import os, requests
def enviar_sms(numero, texto, chave_evento):
r = requests.post(
"https://api.mozout.com/v1/sms/messages",
headers={"Authorization": "Bearer " + os.environ["SMS_API_KEY"],
"Idempotency-Key": chave_evento},
json={"number": numero, "text": texto},
timeout=30,
)
return r.status_code, r.json()
Em Node.js
async function enviarSms(numero, texto, chaveEvento) {
const r = await fetch("https://api.mozout.com/v1/sms/messages", {
method: "POST",
headers: { "Authorization": "Bearer " + process.env.SMS_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": chaveEvento },
body: JSON.stringify({ number: numero, text: texto }),
signal: AbortSignal.timeout(30000),
});
return [r.status, await r.json()];
}
A chave_evento é o que torna a repetição segura: algo como pagamento-3381 ou encomenda-8812-saiu. Com o mesmo valor e o mesmo corpo, a API devolve a resposta guardada em vez de enviar outra vez.
O que fazer com a resposta
| Código | O que fazer |
| 201 | Guardar o id e o status junto do evento. Feito. |
| 422 | Não repetir. Ler details.reason (por exemplo invalid_number ou insufficient_credits) e corrigir ou avisar alguém da equipe. |
| 401 e 403 | Não repetir. A chave falta, está errada, expirou, não tem a permissão sms:write, o IP não está na lista dela, ou a conta não tem o SMS activo (sms_reseller_required). |
| 409 | A mesma chave de evento com outro texto, ou o primeiro pedido ainda em curso. Esperar e repetir igual, ou usar uma chave nova se for mesmo outro envio. |
| 429, 500, 502, 503 | Repetir mais tarde, com a mesma chave de evento. Num 429, esperar pelo menos o tempo do cabeçalho Retry-After. |
| Sem resposta (tempo esgotado) | Repetir com a mesma chave de evento: se o primeiro pedido chegou, a API não envia segundo SMS. |
| Não envie o SMS dentro do pedido do cliente. Se a página de pagamento ficar à espera da API de SMS, um atraso no SMS atrasa o pagamento. Ponha o envio numa fila ou numa tarefa à parte, e deixe a função repetir por lá. |
| Guarde o correlation_id dos erros (vem na resposta e no cabeçalho X-Correlation-ID). Se precisar de ajuda, é o que o suporte pede, junto com a hora e a operação. A chave da API, essa, nunca se envia a ninguém. |
|
Pronto para ligar o seu sistema? Crie uma chave de Sandbox e comece pelo SMS Transaccional. Ver o SMS Transaccional |
PRODUTO RECOMENDADO Hospedagem de sites com cPanel Domínio e SSL incluídos, cópias diárias e o painel que já conhece. desde R$ 36,30/mês (plano de 3 anos, com cupom) Ver planos |











