URL base
Todas las rutas siguientes usan esta URL base y devuelven JSON UTF-8.
https://master-sms.shop/api/v1
Master sms API
Integra números virtuales y recepción de SMS en tu sistema con una API segura y predecible.
Todas las rutas siguientes usan esta URL base y devuelven JSON UTF-8.
https://master-sms.shop/api/v1
Crea una clave en el panel, guarda el secret solo en el servidor y realiza la primera consulta de saldo.
Gestionar clavesEnvía ambas credenciales en cada ruta protegida.
Accept: application/json Content-Type: application/json X-API-Key: your_api_key X-API-Secret: your_api_secret
Los éxitos devuelven success=true y data. Los errores devuelven success=false, error y el estado HTTP correspondiente.
{
"success": true,
"data": {
"example": "value"
},
"timestamp": 1785078000
}{
"success": false,
"error": "Descripción del error",
"code": 400
}Las rutas documentadas corresponden al front controller público de la API v1.
/health
Ruta pública
Confirma que la API está operativa e informa su versión.
{
"success": true,
"data": {
"version": "4.2.0",
"status": "operational",
"timestamp": 1785078000,
"server_time": "2026-07-26 12:00:00",
"request_id": "req_01K123EXAMPLE"
},
"timestamp": 1785078000
}/balance
Requiere autenticación
Devuelve saldo total, bloqueado, disponible y moneda de la cuenta.
{
"success": true,
"data": {
"balance": 1250.5,
"blocked": 50,
"available": 1200.5,
"currency": "BRL",
"limit": 0
},
"timestamp": 1785078000
}/services
Requiere autenticación
Lista países, servicios, operadores, proveedores, precios calculados y stock.
| Parámetro | Tipo | Descripción | Ejemplo |
|---|---|---|---|
country | string | Código numérico del país. | 73 |
service | string | Código del servicio, por ejemplo wa. | wa |
operator | string | Operador específico. También puede ser una lista aceptada por el proveedor. | claro |
available | boolean | Cuando es true, devuelve solo elementos con stock. | true |
provider | string | Nombre o identificador del proveedor. | Hero SMS |
search | string | Búsqueda textual por servicio. | WhatsApp |
GET https://master-sms.shop/api/v1/services?country=73&available=true
{
"success": true,
"data": [
{
"country_id": "73",
"country_name": "Brasil",
"services": [
{
"code": "wa",
"name": "WhatsApp",
"operator": "claro",
"price": 2.5,
"stock": 150,
"provider": "Hero SMS",
"category": "messenger",
"markup": 10
}
]
}
],
"timestamp": 1785078000
}/buy
Requiere autenticación
Compra un número virtual y crea una activación SMS.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
service | string | Sí | Código del servicio, por ejemplo wa. |
country | string | Sí | Código numérico del país. |
request_id | string | Sí | Identificador único del intento de compra para evitar duplicados. |
operator | string | No | Operador específico. También puede ser una lista aceptada por el proveedor. |
provider | string | No | Nombre o identificador del proveedor. |
max_price | number | No | Precio máximo aceptado en la moneda devuelta por la API. |
{
"service": "wa",
"country": "73",
"operator": "claro",
"provider": "Hero SMS",
"max_price": 5,
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"success": true,
"data": {
"activation_id": "ACT17850780001234",
"phone": "5511999999999",
"operator": "claro",
"price": 2.5,
"currency": "BRL",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"service_name": "WhatsApp"
},
"timestamp": 1785078000
}/status?activation_id={id}
Requiere autenticación
Actualiza y devuelve estado, número y código SMS de una activación.
| Parámetro | Obligatorio | Descripción |
|---|---|---|
activation_id | Sí | ID devuelto por la compra. |
| Status | Descripción |
|---|---|
pending | Esperando SMS. |
received | SMS recibido; code contiene el código. |
canceled | Activación cancelada. |
expired | Activación expirada. |
{
"success": true,
"data": {
"activation_id": "ACT17850780001234",
"status": "received",
"phone": "5511999999999",
"created_at": 1785078000,
"code": "123456",
"received_at": 1785078060
},
"timestamp": 1785078060
}/cancel
Requiere autenticación
Cancela una activación elegible e informa el reembolso.
{ "activation_id": "ACT17850780001234" }{
"success": true,
"data": {
"activation_id": "ACT17850780001234",
"status": "canceled",
"refunded": true,
"refund_amount": 2.5
},
"timestamp": 1785078300
}/webhook
Requiere autenticación
Registra, lista y elimina destinos para eventos asíncronos.
| Evento | Descripción |
|---|---|
sms.received | SMS recibido. |
sms.purchased | Número comprado. |
sms.status | Estado de activación modificado. |
balance.low | Saldo por debajo del límite configurado. |
| Campo | Obligatorio | Descripción |
|---|---|---|
event | Sí | Nombre del evento firmado. |
url | Sí | URL HTTPS pública que recibirá un POST JSON. |
secret | No | Secret usado para generar la firma HMAC SHA-256. |
{
"event": "sms.received",
"url": "https://example.com/webhooks/master-sms",
"secret": "replace_with_a_random_secret"
}La lista nunca devuelve el secret almacenado.
{ "webhook_id": 1 }{
"event": "sms.received",
"timestamp": 1785078060,
"data": {
"activation_id": "ACT17850780001234",
"code": "123456",
"phone": "5511999999999",
"service": "wa",
"received_at": 1785078060
},
"signature": "legacy_body_signature"
}/stats
Requiere autenticación
Devuelve totales de compras, SMS recibidos, cancelaciones, gastos y reembolsos.
{
"success": true,
"data": {
"total_compras": 42,
"total_recebidos": 31,
"total_cancelados": 11,
"total_gasto": 79.5,
"total_estornado": 21
},
"timestamp": 1785078000
}/commissions
Requiere autenticación
Devuelve comisiones pendientes, pagadas y el historial del revendedor autenticado.
{
"success": true,
"data": {
"pending_total": 15.3,
"paid_total": 120,
"commissions": []
},
"timestamp": 1785078000
}El cuerpo bruto se firma con HMAC SHA-256. Compara X-Webhook-Signature en tiempo constante antes de procesar JSON.
$rawBody = file_get_contents('php://input');
$received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $rawBody, getenv('MASTER_SMS_WEBHOOK_SECRET'));
if ($received === '' || !hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
$event = json_decode($rawBody, true, flags: JSON_THROW_ON_ERROR);
http_response_code(204);
Clientes mínimos para backend. Adapta timeouts, logs y almacenamiento de secrets a tu entorno.
<?php
final class MasterSmsClient
{
public function __construct(
private string $apiKey,
private string $apiSecret,
private string $baseUrl = 'https://master-sms.shop/api/v1'
) {}
public function request(string $method, string $path, ?array $body = null): array
{
$ch = curl_init(rtrim($this->baseUrl, '/') . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
'X-API-Key: ' . $this->apiKey,
'X-API-Secret: ' . $this->apiSecret,
],
CURLOPT_POSTFIELDS => $body === null ? null : json_encode($body),
]);
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
$result = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);
if ($status < 200 || $status >= 300 || empty($result['success'])) {
throw new RuntimeException($result['error'] ?? "HTTP {$status}", $status);
}
return $result['data'] ?? [];
}
}
$client = new MasterSmsClient(
getenv('MASTER_SMS_API_KEY'),
getenv('MASTER_SMS_API_SECRET')
);
$balance = $client->request('GET', '/balance');
$services = $client->request('GET', '/services?country=73&available=true');
$purchase = $client->request('POST', '/buy', [
'service' => 'wa',
'country' => '73',
'request_id' => bin2hex(random_bytes(16)),
]);
import os
import uuid
import requests
class MasterSmsClient:
def __init__(self):
self.base_url = "https://master-sms.shop/api/v1"
self.session = requests.Session()
self.session.headers.update({
"Accept": "application/json",
"Content-Type": "application/json",
"X-API-Key": os.environ["MASTER_SMS_API_KEY"],
"X-API-Secret": os.environ["MASTER_SMS_API_SECRET"],
})
def request(self, method, path, *, params=None, json=None):
response = self.session.request(
method, self.base_url + path, params=params, json=json, timeout=30
)
payload = response.json()
if not response.ok or not payload.get("success"):
raise RuntimeError(payload.get("error", f"HTTP {response.status_code}"))
return payload.get("data", {})
client = MasterSmsClient()
balance = client.request("GET", "/balance")
services = client.request("GET", "/services", params={
"country": "73", "available": "true"
})
purchase = client.request("POST", "/buy", json={
"service": "wa",
"country": "73",
"request_id": str(uuid.uuid4()),
})
import crypto from "node:crypto";
const baseUrl = "https://master-sms.shop/api/v1";
const headers = {
Accept: "application/json",
"Content-Type": "application/json",
"X-API-Key": process.env.MASTER_SMS_API_KEY,
"X-API-Secret": process.env.MASTER_SMS_API_SECRET,
};
async function request(method, path, body) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30_000);
try {
const response = await fetch(baseUrl + path, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
signal: controller.signal,
});
const payload = await response.json();
if (!response.ok || !payload.success) {
throw new Error(payload.error ?? `HTTP ${response.status}`);
}
return payload.data ?? {};
} finally {
clearTimeout(timeout);
}
}
const balance = await request("GET", "/balance");
const purchase = await request("POST", "/buy", {
service: "wa",
country: "73",
request_id: crypto.randomUUID(),
});
export MASTER_SMS_API_KEY="your_api_key"
export MASTER_SMS_API_SECRET="your_api_secret"
export MASTER_SMS_BASE_URL="https://master-sms.shop/api/v1"
curl --fail-with-body --silent --show-error \
"$MASTER_SMS_BASE_URL/balance" \
-H "Accept: application/json" \
-H "X-API-Key: $MASTER_SMS_API_KEY" \
-H "X-API-Secret: $MASTER_SMS_API_SECRET"
curl --fail-with-body --silent --show-error \
"$MASTER_SMS_BASE_URL/buy" \
-X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-API-Key: $MASTER_SMS_API_KEY" \
-H "X-API-Secret: $MASTER_SMS_API_SECRET" \
--data '{"service":"wa","country":"73","request_id":"550e8400-e29b-41d4-a716-446655440000"}'
Copia este prompt, indica tu stack y envíalo a una IA de programación. Sustituye solo los placeholders; nunca pegues tu API Secret.
| Código | Significado | Tratamiento recomendado |
|---|---|---|
400 | Solicitud inválida | Corrige JSON, campos obligatorios o reglas. |
401 | No autenticado | Comprueba X-API-Key y X-API-Secret. |
402 | Saldo insuficiente | Recarga la cuenta antes de comprar. |
403 | Sin permiso | Activa el permiso o revisa la lista blanca de IP. |
404 | No encontrado | Revisa ruta, servicio, stock o activation_id. |
405 | Método inválido | Usa el método HTTP documentado. |
409 | Conflicto de idempotencia | No reutilices request_id para otra compra. |
429 | Límite excedido | Espera y reintenta con backoff. |
500 | Error interno | Registra request_id y reintenta sin duplicar la compra. |
El límite por minuto depende de la clave y aparece en X-RateLimit-Limit. Ante HTTP 429, usa backoff exponencial con jitter.