
O que precisa
- Uma conta revendedora de SMS activa. Sem ela, a API responde
403com o códigosms_reseller_required. - Uma chave com a permissão
sms:writepara enviar, esms:readpara consultar. Veja Permissões.
O envio
Use POST /v1/sms/messages com o número e o texto:
curl
curl -X POST "https://api.interweb.ao/v1/sms/messages" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}
r = requests.post("https://api.interweb.ao/v1/sms/messages", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}),
});
console.log(response.status);
console.log(await response.text());O número não precisa de indicativo, porque o sistema reconhece o país pelo primeiro algarismo: 841234567 vai para Moçambique e 923456789 para Angola. Com o indicativo também funciona, com ou sem o + e com espaços: +258 84 123 4567 e 258841234567 são o mesmo número. Se o número não for válido, a API responde 422 com validation_failed e o motivo invalid_number em details.reason.
Sem send_at, a mensagem sai logo e a resposta traz o estado real: sent se saiu, failed se falhou, ou queued se tiver de esperar a vez.
Envie o cabeçalho Idempotency-Key para uma repetição nunca enviar duas vezes. Veja Repetições.
O remetente
O campo sender é opcional. Se não o enviar, a mensagem sai com o remetente grátis, NETMSG, que todas as contas podem usar sem pedido.
Para usar outro nome, indique um remetente aprovado. A lista está em GET /v1/sms/senders, com o remetente grátis sempre em primeiro e o campo free a true.
Sandbox e Produção
- Com uma chave
sandbox_, ou enquanto a API está em preparação, a mensagem é simulada: não sai nada e não se gastam créditos. - Com uma chave
prod_, a mensagem é enviada e os créditos são descontados do saldo de SMS. O limite de gastos da chave, em moeda, não se aplica a estes créditos.
Veja Sandbox e Produção.
Envios agendados
Para a mensagem sair mais tarde, junte ao envio o campo send_at, com a data e a hora em ISO 8601 e o fuso horário, por exemplo 2026-11-20T09:30:00+02:00 (hora de Maputo). A data tem de ser no futuro e, no máximo, daqui a 365 dias. Caso contrário, a API responde 422, com o motivo invalid_send_at, send_at_in_past ou send_at_too_far em details.reason.
- A mensagem fica com o estado
schedulede com a hora marcada emscheduled_for. - Ao agendar, a API só confere se o saldo chega. Os créditos só são descontados quando a mensagem sair: até lá,
chargedficafalse, eGET /v1/sms/balancemostra emscheduled_creditso valor agendado que ainda não foi descontado. - Se, na hora marcada, o saldo não chegar, a mensagem não sai e fica
failed, comerrorainsufficient_credits.
Para desistir do envio, use POST /v1/sms/messages/{id}/cancel antes da hora marcada:
curl
curl -X POST "https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
r = requests.post("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
},
});
console.log(response.status);
console.log(await response.text());Só se cancelam as mensagens da própria conta que ainda estejam scheduled. Se os créditos já tiverem sido descontados, voltam ao saldo, e credits_returned diz quantos. Se a mensagem já saiu, está a sair ou já foi cancelada, a API responde 409, com o motivo not_cancellable em details.reason. Com uma chave sandbox_, a API confere tudo e não muda nada.
Ver uma mensagem
Use GET /v1/sms/messages/{id} com o identificador devolvido no envio. A resposta traz o estado, a hora marcada (se a mensagem estiver agendada) e o campo charged, que diz se os créditos já foram descontados. As mensagens simuladas só se vêem com a chave que as criou.
O saldo
Use GET /v1/sms/balance. É o mesmo saldo em Sandbox e em Produção.
Ver as mensagens enviadas
GET /v1/sms/messages devolve as mensagens que a conta enviou, em páginas, com os filtros status, from, to e number. O número vem tapado. Os avisos da conta, os códigos de verificação e as mensagens simuladas não aparecem.
curl
curl "https://api.interweb.ao/v1/sms/messages" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/messages", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Estatísticas
GET /v1/sms/stats dá os totais por estado, os créditos gastos e uma linha por cada dia com mensagens. Sem datas, conta os últimos 30 dias; no máximo 366.
Modelos
GET /v1/sms/templateslista os modelos da conta, eGET /v1/sms/templates/{id}mostra um.POST /v1/sms/templatescria,PATCH /v1/sms/templates/{id}altera eDELETE /v1/sms/templates/{id}apaga.
São os mesmos modelos da página de SMS do portal. Um modelo não envia nada: serve para guardar o texto. O texto aceita as variáveis {$client_name}, {$client_first_name}, {$client_last_name}, {$client_company_name}, {$remetente} e {$data}; outra variável responde 422.
Remetentes novos
POST /v1/sms/senders faz o pedido, com o nome, a entidade, o país, o número fiscal, a finalidade e um exemplo de mensagem. GET /v1/sms/senders/{sender} diz em que ponto está, pelo id ou pelo nome.
curl
curl -X POST "https://api.interweb.ao/v1/sms/senders" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/senders');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}
r = requests.post("https://api.interweb.ao/v1/sms/senders", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/senders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}),
});
console.log(response.status);
console.log(await response.text());A nossa equipa analisa o pedido e trata do registo junto das operadoras; a aprovação depende delas. Se for recusado, note explica porquê e pode pedir de novo com os dados corrigidos. Para juntar documentos, faça o pedido no portal, em documents_url.
Números que não recebem
POST /v1/sms/opt-outs acrescenta um número à lista da conta: a partir daí, enviar para ele responde 422 com number_opted_out. GET /v1/sms/opt-outs mostra a lista. Para retirar um número, fale com o suporte.
Ajuda
Para outras dúvidas, veja a Base de Conhecimento.
Operações
16 operações nesta área. Clique numa operação para ver os parâmetros, os exemplos e as respostas, ou para a experimentar no Playground, sem sair da página.
GETListar as mensagens enviadas
/v1/sms/messages
https://api.interweb.ao/v1/sms/messagesPrecisa de sms:read. As mensagens que esta conta enviou, as mais recentes primeiro. Os avisos da conta e os códigos de verificação não aparecem, nem as mensagens simuladas com uma chave de Sandbox. O número vem tapado. Se uma mensagem falhar, error é delivery_failed. charged diz se os créditos já saíram do saldo.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
status | consulta | string: scheduled, queued, sending, sent, simulated, failed, cancelled | não | Só este estado. |
from | consulta | string (date) | não | Primeiro dia, AAAA-MM-DD. |
to | consulta | string (date) | não | Último dia, AAAA-MM-DD. |
number | consulta | string | não | Só este número, com ou sem indicativo. |
page | consulta | integer | não | O número da página. A primeira é a 1. |
per_page | consulta | integer | não | Resultados por página, de 1 a 100. Por omissão, 10. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/messages" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/messages", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Listar as mensagens enviadas.
{
"data": [
{
"id": "128",
"status": "sent",
"simulated": false,
"to": "25884****567",
"sender": "NETMSG",
"text": "A sua encomenda está pronta.",
"parts": 1,
"encoding": "GSM",
"credits": 1.0,
"campaign_id": null,
"error": null,
"scheduled_for": "2026-11-05T09:30:00+02:00",
"created_at": "2026-11-05T09:30:00+02:00",
"sent_at": "2026-11-05T09:30:04+02:00",
"charged": true
}
],
"meta": {
"page": 1,
"per_page": 10,
"total": 1,
"total_pages": 1
}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
POSTEnviar um SMS
/v1/sms/messages
https://api.interweb.ao/v1/sms/messagesPrecisa de sms:write e de uma conta revendedora de SMS activa. Com uma chave de Sandbox, ou enquanto a API está em preparação, a mensagem é simulada: não sai nada e não se gastam créditos. Com uma chave de Produção, a mensagem entra na fila e os créditos saem do saldo de SMS (o limite de gastos da chave, em moeda, não se aplica a estes créditos). Envie Idempotency-Key para uma repetição nunca enviar duas vezes. Sem send_at a mensagem sai logo e a resposta traz o estado real: sent, failed, ou queued se tiver de esperar a vez. Com send_at fica scheduled: agora só se confere o saldo, e os créditos saem dele quando a mensagem sair (charged fica false até lá); se nessa hora o saldo não chegar, a mensagem não sai e fica failed, com error a insufficient_credits. Uma mensagem agendada pode ser cancelada com POST /v1/sms/messages/{id}/cancel.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
Idempotency-Key | cabeçalho | string | não | Um valor único qualquer, até 255 caracteres visíveis. Vale 24 horas por chave. Repetir o mesmo pedido devolve a resposta guardada; outro corpo, ou um primeiro pedido ainda em curso, devolve 409. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Corpo do pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
number | string | sim | Com ou sem indicativo, e pode ter espaços: +258841234567, 258 84 123 4567 ou 84 123 4567. Os telemóveis de Moçambique e de Angola reconhecem-se sozinhos; qualquer outro sem indicativo segue o país da sua conta. |
text | string | sim | |
sender | string | não | Opcional. Um remetente aprovado; se faltar, o remetente grátis (veja GET /v1/sms/senders). |
send_at | string (date-time) | não | Opcional. Agenda a mensagem: data e hora em ISO 8601 com o fuso horário, como 2026-11-20T09:30:00+02:00. Tem de ser no futuro e, no máximo, daqui a 365 dias. Sem este campo, a mensagem sai logo. |
Exemplos
curl
curl -X POST "https://api.interweb.ao/v1/sms/messages" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}
r = requests.post("https://api.interweb.ao/v1/sms/messages", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"number": "+258841234567", "text": "Your order is ready.", "send_at": "2026-11-20T09:30:00+02:00"}),
});
console.log(response.status);
console.log(await response.text());Respostas
201
A mensagem: enviada, simulada, agendada ou à espera na fila.
{
"data": {
"id": "412",
"status": "scheduled",
"simulated": false,
"to": "25884****567",
"sender": "NETMSG",
"parts": 1,
"encoding": "GSM",
"credits": 1.0,
"charged": false,
"mode": "production",
"error": null,
"scheduled_for": "2026-11-20T09:30:00+02:00",
"created_at": "2026-11-10T12:00:00+02:00",
"sent_at": null
},
"meta": {}
}| Campo | Tipo | Descrição |
|---|---|---|
data.id | string | Um número nas mensagens que entraram na fila, um UUID nas simuladas. |
data.status | string: scheduled, queued, sending, sent, simulated, failed, cancelled | scheduled: à espera da hora em scheduled_for, e ainda se pode cancelar. queued: à espera da vez para sair. |
data.simulated | boolean | Verdadeiro quando o SMS é simulado e não sai nenhuma mensagem. |
data.to | string | O número, em parte tapado. |
data.credits | number | Quanto custa a mensagem, em créditos. Veja charged para saber se já saíram do saldo de SMS. Sempre 0 quando a API simula. |
data.would_cost | number | Só nas simuladas: quanto custaria o envio em Produção. |
data.error | string, null | delivery_failed quando não foi possível entregar; insufficient_credits quando uma mensagem agendada não tinha saldo suficiente na hora de sair. |
data.charged | boolean | Verdadeiro quando os créditos saíram do saldo de SMS. Uma mensagem agendada só se cobra quando sai; as falhadas, canceladas e simuladas devolvem os créditos. |
data.scheduled_for | string, null (date-time) | A hora escolhida em send_at, enquanto a mensagem está agendada ou depois de cancelada; nos outros casos, null. |
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
X-API-Simulated | Presente e true quando esta escrita foi simulada: nada mudou e nada foi cobrado. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}409
A Idempotency-Key foi usada com outro pedido, ou o primeiro pedido ainda está em curso.
{
"error": {
"code": "idempotency_conflict",
"message": "Esta Idempotency-Key já foi usada com outro pedido, ou o primeiro pedido ainda está em curso.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"reason": "different_request"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | sms_reseller_required, insufficient_scope, forbidden | Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden). |
| 409 | idempotency_conflict | A Idempotency-Key foi usada com outro pedido, ou o primeiro pedido ainda está em curso. |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETVer um SMS
/v1/sms/messages/{id}
https://api.interweb.ao/v1/sms/messages/{id}Precisa de sms:read. As mensagens simuladas só se vêem com a chave que as criou.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id | caminho | string | sim | O id devolvido ao enviar. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
A mensagem.
{
"data": {
"id": "7f0c9d2e-3a51-4c7e-9b1a-2d4f6a8b0c11",
"status": "simulated",
"simulated": true,
"to": "25884****567",
"sender": "NETMSG",
"parts": 1,
"encoding": "GSM",
"would_cost": 1,
"mode": "sandbox",
"credits": 0,
"created_at": "2026-11-04T10:00:00+02:00",
"error": null,
"sent_at": null,
"charged": false,
"scheduled_for": null
},
"meta": {}
}| Campo | Tipo | Descrição |
|---|---|---|
data.id | string | Um número nas mensagens que entraram na fila, um UUID nas simuladas. |
data.status | string: scheduled, queued, sending, sent, simulated, failed, cancelled | scheduled: à espera da hora em scheduled_for, e ainda se pode cancelar. queued: à espera da vez para sair. |
data.simulated | boolean | Verdadeiro quando o SMS é simulado e não sai nenhuma mensagem. |
data.to | string | O número, em parte tapado. |
data.credits | number | Quanto custa a mensagem, em créditos. Veja charged para saber se já saíram do saldo de SMS. Sempre 0 quando a API simula. |
data.would_cost | number | Só nas simuladas: quanto custaria o envio em Produção. |
data.error | string, null | delivery_failed quando não foi possível entregar; insufficient_credits quando uma mensagem agendada não tinha saldo suficiente na hora de sair. |
data.charged | boolean | Verdadeiro quando os créditos saíram do saldo de SMS. Uma mensagem agendada só se cobra quando sai; as falhadas, canceladas e simuladas devolvem os créditos. |
data.scheduled_for | string, null (date-time) | A hora escolhida em send_at, enquanto a mensagem está agendada ou depois de cancelada; nos outros casos, null. |
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | sms_reseller_required, insufficient_scope, forbidden | Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden). |
| 404 | not_found | Não encontrado. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETVer o saldo de SMS
/v1/sms/balance
https://api.interweb.ao/v1/sms/balancePrecisa de sms:read. O saldo é o verdadeiro nos dois modos.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/balance" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/balance');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/balance", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/balance", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Saldo e limite diário.
{
"data": {
"balance": 50,
"unit": "credits",
"daily_limit": 200,
"sent_today": 3,
"mode": "sandbox",
"scheduled_credits": 0.0
},
"meta": {}
}| Campo | Tipo | Descrição |
|---|---|---|
data.scheduled_credits | number | Créditos das mensagens agendadas que ainda não foram cobradas. Continuam em balance e saem quando cada mensagem sair. |
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | sms_reseller_required, insufficient_scope, forbidden | Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden). |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETListar os remetentes de SMS
/v1/sms/senders
https://api.interweb.ao/v1/sms/sendersPrecisa de sms:read. O remetente grátis vem sempre em primeiro, com free: true.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/senders" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/senders');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/senders", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/senders", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Os remetentes desta conta.
{
"data": [
{
"sender": "NETMSG",
"status": "approved",
"free": true
},
{
"sender": "MINHAEMPRESA",
"status": "pending",
"free": false
}
],
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | sms_reseller_required, insufficient_scope, forbidden | Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden). |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
POSTPedir um remetente
/v1/sms/senders
https://api.interweb.ao/v1/sms/sendersPrecisa de sms:write. O nome tem até 11 caracteres, entre letras, números e espaços. Cada conta tem até 30 remetentes. A equipa analisa o pedido e regista-o junto das operadoras; a aprovação depende delas. Depois de uma recusa, envie de novo com os dados corrigidos. Os documentos enviam-se no portal da conta, quando o pedido é feito lá. Limite de 20 alterações por minuto.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Idempotency-Key | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |
Corpo do pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
sender | string | sim | |
entity | string | sim | |
country | string | sim | |
tax_id | string | sim | |
purpose | string | sim | |
sample | string | sim |
Exemplos
curl
curl -X POST "https://api.interweb.ao/v1/sms/senders" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/senders');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}
r = requests.post("https://api.interweb.ao/v1/sms/senders", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/senders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"sender": "AMINHAMARCA", "entity": "A Minha Empresa, Lda", "country": "Moçambique", "tax_id": "123456789", "purpose": "Avisos de encomenda aos nossos clientes.", "sample": "A sua encomenda está pronta."}),
});
console.log(response.status);
console.log(await response.text());Respostas
201
Pedir um remetente.
{
"data": {
"id": 7,
"sender": "AMINHAMARCA",
"status": "pending",
"free": false,
"entity": "A Minha Empresa, Lda",
"country": "Moçambique",
"purpose": "Avisos de encomenda aos nossos clientes.",
"sample": "A sua encomenda está pronta.",
"note": null,
"documents": 0,
"documents_url": "https://my.example.com/sms-center.php?view=senders&language=portuguese¤cy=5",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00",
"simulated": true
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}409
A operação não se pode fazer no estado actual. Veja details.reason.
{
"error": {
"code": "conflict",
"message": "This operation only works on an active domain.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"reason": "domain_not_active"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 409 | conflict | A operação não se pode fazer no estado actual. Veja details.reason. |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETVer as estatísticas de envio
/v1/sms/stats
https://api.interweb.ao/v1/sms/statsPrecisa de sms:read. Totais e uma linha por cada dia com mensagens. Sem datas, os últimos 30 dias; no máximo 366 dias. As mensagens falhadas, canceladas e simuladas não contam em credits_spent. Também não contam as mensagens agendadas que ainda não foram cobradas.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
from | consulta | string (date) | não | Primeiro dia, AAAA-MM-DD. |
to | consulta | string (date) | não | Último dia, AAAA-MM-DD. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/stats" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/stats');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/stats", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/stats", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Ver as estatísticas de envio.
{
"data": {
"from": "2026-10-07",
"to": "2026-11-05",
"messages": 12,
"parts": 14,
"credits_spent": 13.0,
"by_status": {
"scheduled": 0,
"queued": 0,
"sending": 0,
"sent": 11,
"simulated": 0,
"failed": 1,
"cancelled": 0
},
"by_day": [
{
"date": "2026-11-05",
"messages": 12,
"sent": 11,
"failed": 1,
"credits": 13.0
}
]
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETListar os modelos
/v1/sms/templates
https://api.interweb.ao/v1/sms/templatesPrecisa de sms:read. Os modelos desta conta, por nome.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
category | consulta | string: general, notice, promotion, billing, confirmation | não | Só esta categoria. |
language | consulta | string: pt, en | não | Só esta língua. |
page | consulta | integer | não | O número da página. A primeira é a 1. |
per_page | consulta | integer | não | Resultados por página, de 1 a 100. Por omissão, 10. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/templates" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/templates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/templates", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/templates", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Listar os modelos.
{
"data": [
{
"id": 41,
"name": "Aviso de factura",
"text": "Olá {$client_first_name}, a sua factura vence hoje.",
"category": "notice",
"language": "pt",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00"
}
],
"meta": {
"page": 1,
"per_page": 10,
"total": 1,
"total_pages": 1
}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
POSTCriar um modelo
/v1/sms/templates
https://api.interweb.ao/v1/sms/templatesPrecisa de sms:write. O nome não se pode repetir na conta. O texto aceita {$client_name}, {$client_first_name}, {$client_last_name}, {$client_company_name}, {$remetente} e {$data}. Limite de 20 alterações por minuto.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Idempotency-Key | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |
Corpo do pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | sim | |
text | string | sim | |
category | string: general, notice, promotion, billing, confirmation | não | |
language | string: pt, en | não |
Exemplos
curl
curl -X POST "https://api.interweb.ao/v1/sms/templates" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"name": "Aviso de factura", "text": "Olá {$client_first_name}, a sua factura vence hoje.", "category": "notice", "language": "pt"}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/templates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"name": "Aviso de factura", "text": "Olá {$client_first_name}, a sua factura vence hoje.", "category": "notice", "language": "pt"}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"name": "Aviso de factura", "text": "Olá {$client_first_name}, a sua factura vence hoje.", "category": "notice", "language": "pt"}
r = requests.post("https://api.interweb.ao/v1/sms/templates", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/templates", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "Aviso de factura", "text": "Olá {$client_first_name}, a sua factura vence hoje.", "category": "notice", "language": "pt"}),
});
console.log(response.status);
console.log(await response.text());Respostas
201
Criar um modelo.
{
"data": {
"id": 41,
"name": "Aviso de factura",
"text": "Olá {$client_first_name}, a sua factura vence hoje.",
"category": "notice",
"language": "pt",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00",
"simulated": true
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}409
A operação não se pode fazer no estado actual. Veja details.reason.
{
"error": {
"code": "conflict",
"message": "This operation only works on an active domain.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"reason": "domain_not_active"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 409 | conflict | A operação não se pode fazer no estado actual. Veja details.reason. |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETVer um modelo
/v1/sms/templates/{id}
https://api.interweb.ao/v1/sms/templates/{id}Precisa de sms:read. Um modelo desta conta.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id | caminho | string | sim | O id do modelo. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Ver um modelo.
{
"data": {
"id": 41,
"name": "Aviso de factura",
"text": "Olá {$client_first_name}, a sua factura vence hoje.",
"category": "notice",
"language": "pt",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00"
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 404 | not_found | Não encontrado. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
PATCHAlterar um modelo
/v1/sms/templates/{id}
https://api.interweb.ao/v1/sms/templates/{id}Precisa de sms:write. Envie só os campos a alterar. Limite de 20 alterações por minuto.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id | caminho | string | sim | O id do modelo. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Corpo do pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | não | |
text | string | não | |
category | string: general, notice, promotion, billing, confirmation | não | |
language | string: pt, en | não |
Exemplos
curl
curl -X PATCH "https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Content-Type: application/json" \
-d '{"text": "Olá {$client_first_name}, a sua factura vence amanhã."}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => '{"text": "Olá {$client_first_name}, a sua factura vence amanhã."}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
payload = {"text": "Olá {$client_first_name}, a sua factura vence amanhã."}
r = requests.patch("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Content-Type": "application/json",
},
body: JSON.stringify({"text": "Olá {$client_first_name}, a sua factura vence amanhã."}),
});
console.log(response.status);
console.log(await response.text());Respostas
200
Alterar um modelo.
{
"data": {
"id": 41,
"name": "Aviso de factura",
"text": "Olá {$client_first_name}, a sua factura vence hoje.",
"category": "notice",
"language": "pt",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00",
"simulated": true
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}409
A operação não se pode fazer no estado actual. Veja details.reason.
{
"error": {
"code": "conflict",
"message": "This operation only works on an active domain.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"reason": "domain_not_active"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 404 | not_found | Não encontrado. |
| 409 | conflict | A operação não se pode fazer no estado actual. Veja details.reason. |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
DELETEApagar um modelo
/v1/sms/templates/{id}
https://api.interweb.ao/v1/sms/templates/{id}Precisa de sms:write. Os modelos padrão que forem apagados não voltam. Limite de 20 alterações por minuto.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id | caminho | string | sim | O id do modelo. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl -X DELETE "https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.delete("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/templates/00000000-0000-4000-8000-000000000000", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Apagar um modelo.
{
"data": {
"id": 41,
"deleted": false,
"simulated": true
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 404 | not_found | Não encontrado. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETVer um pedido de remetente
/v1/sms/senders/{sender}
https://api.interweb.ao/v1/sms/senders/{sender}Precisa de sms:read. Pelo id ou pelo nome. note é a nota da nossa equipa. O remetente grátis responde sempre approved.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
sender | caminho | string | sim | O id do pedido ou o nome do remetente. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/senders/VALUE" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/senders/VALUE');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/senders/VALUE", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/senders/VALUE", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Ver um pedido de remetente.
{
"data": {
"id": 7,
"sender": "AMINHAMARCA",
"status": "pending",
"free": false,
"entity": "A Minha Empresa, Lda",
"country": "Moçambique",
"purpose": "Avisos de encomenda aos nossos clientes.",
"sample": "A sua encomenda está pronta.",
"note": null,
"documents": 0,
"documents_url": "https://my.example.com/sms-center.php?view=senders&language=portuguese¤cy=5",
"created_at": "2026-11-05T09:30:00+02:00",
"updated_at": "2026-11-05T09:30:00+02:00"
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 404 | not_found | Não encontrado. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
GETListar os números que não recebem
/v1/sms/opt-outs
https://api.interweb.ao/v1/sms/opt-outsPrecisa de sms:read. Os números que esta conta bloqueou, tapados. Use number para confirmar um.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:read.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
number | consulta | string | não | Só este número, com ou sem indicativo. |
page | consulta | integer | não | O número da página. A primeira é a 1. |
per_page | consulta | integer | não | Resultados por página, de 1 a 100. Por omissão, 10. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl "https://api.interweb.ao/v1/sms/opt-outs" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/opt-outs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
}
r = requests.get("https://api.interweb.ao/v1/sms/opt-outs", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/opt-outs", {
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Listar os números que não recebem.
{
"data": [
{
"number": "25884****567",
"created_at": "2026-11-05T09:30:00+02:00"
}
],
"meta": {
"page": 1,
"per_page": 10,
"total": 1,
"total_pages": 1
}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
POSTDeixar de enviar a um número
/v1/sms/opt-outs
https://api.interweb.ao/v1/sms/opt-outsPrecisa de sms:write. A partir daqui, enviar para este número responde 422 com number_opted_out. Para retirar um número da lista, fale com o suporte. Limite de 20 alterações por minuto.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Idempotency-Key | cabeçalho | string | não | Identificador único deste pedido, para o repetir sem o duplicar. |
Corpo do pedido
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
number | string | sim |
Exemplos
curl
curl -X POST "https://api.interweb.ao/v1/sms/opt-outs" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example" \
-H "Content-Type: application/json" \
-d '{"number": "+258841234567"}'PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/opt-outs');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => '{"number": "+258841234567"}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
'Content-Type: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
payload = {"number": "+258841234567"}
r = requests.post("https://api.interweb.ao/v1/sms/opt-outs", headers=headers, json=payload, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/opt-outs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
"Content-Type": "application/json",
},
body: JSON.stringify({"number": "+258841234567"}),
});
console.log(response.status);
console.log(await response.text());Respostas
201
Deixar de enviar a um número.
{
"data": {
"number": "25884****567",
"created_at": "2026-11-05T09:30:00+02:00",
"already_listed": false,
"simulated": true
},
"meta": {}
}| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}422
Alguns dados não são válidos.
{
"error": {
"code": "validation_failed",
"message": "Alguns dados não são válidos.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | forbidden, insufficient_scope, ip_not_allowed | A conta não pode usar a API (forbidden), a chave não tem a permissão necessária (insufficient_scope), ou o endereço IP não está na lista da chave (ip_not_allowed). |
| 422 | validation_failed | Alguns dados não são válidos. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
POSTCancelar um SMS agendado
/v1/sms/messages/{id}/cancel
https://api.interweb.ao/v1/sms/messages/{id}/cancelPrecisa de sms:write. Só se cancelam mensagens desta conta que ainda estejam scheduled. Se os créditos já tiverem sido cobrados, voltam ao saldo, e credits_returned diz quantos; normalmente uma mensagem agendada só se cobra quando sai, e por isso muitas vezes não há nada a devolver. Uma mensagem que já saiu, que está a sair ou que já foi cancelada responde 409, com details.reason a not_cancellable. Com uma chave de Sandbox, ou enquanto a API está em preparação, confere tudo e não muda nada. Envie Idempotency-Key para uma repetição dar a mesma resposta.
Autenticação
Precisa de uma chave válida no cabeçalho Authorization: Bearer. Permissão necessária: sms:write.
Parâmetros
| Nome | Onde | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id | caminho | string | sim | O id devolvido ao enviar. |
Idempotency-Key | cabeçalho | string | não | Um valor único qualquer, até 255 caracteres visíveis. Vale 24 horas por chave. Repetir o mesmo pedido devolve a resposta guardada; outro corpo, ou um primeiro pedido ainda em curso, devolve 409. |
X-API-Mode | cabeçalho | string: sandbox, production | não | Opcional. Se não coincidir com o modo da chave, o pedido é recusado com invalid_request e a razão mode_mismatch. Serve para garantir que um programa nunca corre com a chave errada. |
Exemplos
curl
curl -X POST "https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel" \
-H "Authorization: Bearer $RLX_API_KEY" \
-H "Accept-Language: pt" \
-H "Idempotency-Key: 9f1c2d3e-example"PHP
<?php
$ch = curl_init('https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RLX_API_KEY'),
'Accept-Language: pt',
'Idempotency-Key: 9f1c2d3e-example',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $status, PHP_EOL, $body, PHP_EOL;Python
import os
import requests
headers = {
"Authorization": "Bearer " + os.environ["RLX_API_KEY"],
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
}
r = requests.post("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel", headers=headers, timeout=30)
print(r.status_code)
print(r.text)JavaScript
const response = await fetch("https://api.interweb.ao/v1/sms/messages/00000000-0000-4000-8000-000000000000/cancel", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RLX_API_KEY}`,
"Accept-Language": "pt",
"Idempotency-Key": "9f1c2d3e-example",
},
});
console.log(response.status);
console.log(await response.text());Respostas
200
Cancelar um SMS agendado.
{
"data": {
"id": "412",
"status": "cancelled",
"simulated": false,
"to": "25884****567",
"sender": "NETMSG",
"parts": 1,
"encoding": "GSM",
"credits": 1.0,
"charged": false,
"mode": "production",
"error": null,
"scheduled_for": "2026-11-20T09:30:00+02:00",
"created_at": "2026-11-10T12:00:00+02:00",
"sent_at": null,
"credits_returned": 0.0
},
"meta": {}
}| Campo | Tipo | Descrição |
|---|---|---|
data.id | string | Um número nas mensagens que entraram na fila, um UUID nas simuladas. |
data.status | string: scheduled, queued, sending, sent, simulated, failed, cancelled | scheduled: à espera da hora em scheduled_for, e ainda se pode cancelar. queued: à espera da vez para sair. |
data.simulated | boolean | Verdadeiro quando o SMS é simulado e não sai nenhuma mensagem. |
data.to | string | O número, em parte tapado. |
data.credits | number | Quanto custa a mensagem, em créditos. Veja charged para saber se já saíram do saldo de SMS. Sempre 0 quando a API simula. |
data.would_cost | number | Só nas simuladas: quanto custaria o envio em Produção. |
data.error | string, null | delivery_failed quando não foi possível entregar; insufficient_credits quando uma mensagem agendada não tinha saldo suficiente na hora de sair. |
data.charged | boolean | Verdadeiro quando os créditos saíram do saldo de SMS. Uma mensagem agendada só se cobra quando sai; as falhadas, canceladas e simuladas devolvem os créditos. |
data.scheduled_for | string, null (date-time) | A hora escolhida em send_at, enquanto a mensagem está agendada ou depois de cancelada; nos outros casos, null. |
data.credits_returned | number | Créditos que voltaram ao saldo de SMS com este cancelamento. |
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID | Identificador deste pedido. Indique-o ao suporte se comunicar um problema. |
X-RateLimit-Limit | Pedidos permitidos por minuto. |
X-RateLimit-Remaining | Pedidos que restam no minuto actual. |
X-RateLimit-Reset | Quando acaba o minuto, em segundos Unix. |
X-API-Mode | O modo da chave que fez o pedido: sandbox ou production. |
X-API-Simulated | Presente e true quando esta escrita foi simulada: nada mudou e nada foi cobrado. |
401
A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta.
{
"error": {
"code": "unauthorized",
"message": "Chave da API em falta ou inválida.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}403
Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden).
{
"error": {
"code": "insufficient_scope",
"message": "Esta chave não tem a permissão necessária.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"required": "dns:read"
}
}
}404
Não encontrado.
{
"error": {
"code": "not_found",
"message": "Não encontrado.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}409
A operação não se pode fazer no estado actual. Veja details.reason.
{
"error": {
"code": "conflict",
"message": "This operation only works on an active domain.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"reason": "domain_not_active"
}
}
}429
Demasiados pedidos. Espere o tempo indicado em Retry-After.
{
"error": {
"code": "rate_limited",
"message": "Demasiados pedidos. Tente de novo daqui a pouco.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {
"retry_after": 42
}
}
}| Cabeçalho | Descrição |
|---|---|
Retry-After | Segundos a esperar antes de tentar de novo. |
500
Ocorreu um erro interno. Indique o correlation_id ao suporte.
{
"error": {
"code": "internal_error",
"message": "Ocorreu um erro interno. Indique o correlation_id ao suporte.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}503
A API está desligada.
{
"error": {
"code": "disabled",
"message": "A API está desligada de momento.",
"correlation_id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"details": {}
}
}Erros
| Estado | Código | Significado |
|---|---|---|
| 401 | unauthorized | A chave está em falta, não é válida, foi revogada ou passou da validade, ou quem a criou já não tem acesso à conta. |
| 403 | sms_reseller_required, insufficient_scope, forbidden | Esta conta não tem revenda de SMS activa (sms_reseller_required), a chave não tem a permissão (insufficient_scope), ou a conta não pode usar a API (forbidden). |
| 404 | not_found | Não encontrado. |
| 409 | conflict | A operação não se pode fazer no estado actual. Veja details.reason. |
| 429 | rate_limited | Demasiados pedidos. Espere o tempo indicado em Retry-After. |
| 500 | internal_error | Ocorreu um erro interno. Indique o correlation_id ao suporte. |
| 503 | disabled | A API está desligada. |
O formato dos erros está explicado em Erros.
Nenhuma operação encontrada.