API Master sms

Documentação oficial para integração com nossa plataforma de SMS

Versão 3.0.0

URL Base

Todas as requisições devem usar a seguinte URL base:

https://master-sms.shop/api/v1/

Autenticação

Todas as requisições (exceto endpoints públicos) devem incluir suas credenciais de API nos headers:

X-API-Key: sua_api_key
X-API-Secret: seu_api_secret
Importante: A API Secret é como uma senha. Nunca a compartilhe ou exponha em código front-end.

Suas credenciais podem ser geradas no painel do cliente em API Keys.

Exemplo de requisição autenticada:

curl -X GET "https://master-sms.shop/api/v1/balance" \
  -H "X-API-Key: sua_api_key" \
  -H "X-API-Secret: seu_api_secret"

Endpoints Disponíveis

Consultar Saldo

GET /balance
Retorna o saldo atual da sua conta

Exemplo de resposta (200 OK):

{
    "success": true,
    "data": {
        "balance": 1250.50,
        "blocked": 50.00,
        "available": 1200.50,
        "currency": "BRL",
        "limit": 0
    },
    "timestamp": 1704067200
}

Listar Serviços

GET /services
Lista todos os serviços disponíveis com preços e estoque

Parâmetros (opcionais):

Parâmetro Tipo Descrição Exemplo
countrystringFiltrar por país (código numérico)73 (Brasil)
servicestringFiltrar por serviço específicowa (WhatsApp)
operatorstringFiltrar por operadoraclaro, vivo
availablebooleanApenas serviços com estoquetrue
providerstringFiltrar por provedorprovedor 2, provedor 1

Exemplo de requisição:

GET https://master-sms.shop/api/v1/services?country=73&available=true

Exemplo de resposta:

{
    "success": true,
    "data": [
        {
            "country_id": "73",
            "country_name": "Brasil",
            "services": [
                { "code": "wa", "name": "WhatsApp", "operator": "claro", "price": 2.50, "stock": 150, "provider": "provedor 1" },
                { "code": "tg", "name": "Telegram", "operator": "vivo", "price": 1.80, "stock": 75, "provider": "provedor 2" }
            ]
        }
    ],
    "timestamp": 1704067200
}

Comprar Número

POST /buy
Compra um número para ativação de SMS

Body (JSON):

CampoTipoObrigatórioDescriçãoExemplo
servicestringsimCódigo do serviço"wa"
countrystringsimCódigo do país"73"
operatorstringnãoOperadora específica"claro"
max_pricefloatnãoPreço máximo em BRL5.00
request_idstringnãoID único para evitar duplicatas"req_123456"
Dica: Use o campo request_id para garantir que a mesma compra não seja processada múltiplas vezes em caso de falhas de rede.

Exemplo de requisição:

{
    "service": "wa",
    "country": "73",
    "operator": "claro",
    "max_price": 5.00,
    "request_id": "req_1784833505"
}

Exemplo de resposta (sucesso):

{
    "success": true,
    "data": {
        "activation_id": "ACT17040672001234",
        "phone": "5511999999999",
        "operator": "claro",
        "price": 2.50,
        "currency": "BRL",
        "request_id": "req_123456"
    },
    "timestamp": 1704067200
}

Verificar Status

GET /status?activation_id={id}
Verifica o status de uma ativação

Parâmetros:

ParâmetroObrigatórioDescrição
activation_idsimID da ativação recebido na compra

Status possíveis:

StatusDescrição
pendingAguardando recebimento do SMS
receivedSMS recebido com sucesso
canceledAtivação cancelada
expiredTempo limite excedido (20 minutos)

Exemplo de resposta (pending):

{
    "success": true,
    "data": {
        "activation_id": "ACT17040672001234",
        "status": "pending",
        "phone": "5511999999999",
        "created_at": 1704067200
    },
    "timestamp": 1704067260
}

Exemplo de resposta (received):

{
    "success": true,
    "data": {
        "activation_id": "ACT17040672001234",
        "status": "received",
        "code": "123456",
        "phone": "5511999999999",
        "created_at": 1704067200,
        "received_at": 1704067260
    },
    "timestamp": 1704067260
}

Cancelar Ativação

POST /cancel
Cancela uma ativação ativa (após 5 minutos)
Importante: Só é possível cancelar após 5 minutos da compra. Cancelamentos antes disso são negados.

Body (JSON):

{ "activation_id": "ACT17040672001234" }

Exemplo de resposta:

{
    "success": true,
    "data": {
        "activation_id": "ACT17040672001234",
        "status": "canceled",
        "refunded": true
    },
    "timestamp": 1704067260
}

Webhooks

Configure webhooks para receber notificações em tempo real sobre eventos da sua conta.

Eventos disponíveis:

EventoDescrição
sms.receivedDisparado quando um SMS é recebido
sms.purchasedDisparado quando um número é comprado
balance.lowDisparado quando o saldo está abaixo do limite (R$ 50)

Registrar webhook:

POST /webhook

Body (JSON):

{
    "event": "sms.received",
    "url": "https://seu-dominio.com/webhook/sms",
    "secret": "seu_secret_opcional"
}

Exemplo de payload recebido (sms.received):

{
    "event": "sms.received",
    "timestamp": 1704067200,
    "data": {
        "activation_id": "ACT17040672001234",
        "code": "123456",
        "phone": "5511999999999",
        "service": "wa"
    }
}

Listar webhooks:

GET /webhook

Remover webhook:

DELETE /webhook

Body:

{ "webhook_id": 1 }

Exemplos de Integração

PHP
Python
Node.js
cURL
JavaScript

PHP - Cliente completo


<?php
/**
 * Cliente para API SMS Provider
 * Requisitos: PHP 7.4+, cURL, JSON
 */
class SMSProviderClient {
    private $apiKey;
    private $apiSecret;
    private $baseUrl;
    
    public function __construct($apiKey, $apiSecret, $baseUrl = 'https://master-sms.shop/api/v1') {
        $this->apiKey = $apiKey;
        $this->apiSecret = $apiSecret;
        $this->baseUrl = rtrim($baseUrl, '/');
    }
    
    private function request($endpoint, $method = 'GET', $data = null) {
        $ch = curl_init($this->baseUrl . $endpoint);
        $headers = [ 'X-API-Key: ' . $this->apiKey, 'X-API-Secret: ' . $this->apiSecret, 'Content-Type: application/json' ];
        curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => true ]);
        if ($data) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if (curl_error($ch)) throw new Exception('Erro cURL: ' . curl_error($ch));
        curl_close($ch);
        $result = json_decode($response, true);
        if (!$result || !isset($result['success'])) throw new Exception('Resposta inválida da API');
        if ($httpCode !== 200 || !$result['success']) {
            $error = $result['error'] ?? 'Erro desconhecido';
            throw new Exception($error, $httpCode);
        }
        return $result['data'] ?? $result;
    }
    
    public function getBalance() { return $this->request('/balance'); }
    public function getServices($filters = []) {
        $query = http_build_query($filters);
        return $this->request('/services?' . $query);
    }
    public function buyNumber($service, $country, $operator = null, $maxPrice = null, $requestId = null) {
        $data = [ 'service' => $service, 'country' => $country ];
        if ($operator) $data['operator'] = $operator;
        if ($maxPrice) $data['max_price'] = $maxPrice;
        if ($requestId) $data['request_id'] = $requestId;
        return $this->request('/buy', 'POST', $data);
    }
    public function checkStatus($activationId) { return $this->request('/status?activation_id=' . urlencode($activationId)); }
    public function cancelActivation($activationId) { return $this->request('/cancel', 'POST', ['activation_id' => $activationId]); }
    public function registerWebhook($event, $url, $secret = null) {
        $data = ['event' => $event, 'url' => $url];
        if ($secret) $data['secret'] = $secret;
        return $this->request('/webhook', 'POST', $data);
    }
    public function listWebhooks() { return $this->request('/webhook'); }
    public function deleteWebhook($webhookId) { return $this->request('/webhook', 'DELETE', ['webhook_id' => $webhookId]); }
}

try {
    $client = new SMSProviderClient('sua_api_key', 'seu_api_secret');
    $balance = $client->getBalance();
    echo "Saldo disponível: R$ " . number_format($balance['available'], 2, ',', '.') . "\n";
    $services = $client->getServices(['country' => '73', 'available' => true]);
    foreach ($services as $country) {
        echo "\nPaís: {$country['country_name']}\n";
        foreach ($country['services'] as $service) {
            echo "  - {$service['name']}: R$ " . number_format($service['price'], 2, ',', '.') . " (estoque: {$service['stock']})\n";
        }
    }
    $requestId = 'req_' . time();
    $result = $client->buyNumber('wa', '73', 'claro', 5.00, $requestId);
    echo "\nNúmero comprado: {$result['phone']}\nActivation ID: {$result['activation_id']}\n";
} catch (Exception $e) { echo "Erro: " . $e->getMessage() . "\n"; }
?>

Python - Cliente completo


import requests
from typing import Optional, Dict

class SMSProviderClient:
    def __init__(self, api_key: str, api_secret: str, base_url: str = 'https://master-sms.shop/api/v1'):
        self.api_key = api_key
        self.api_secret = api_secret
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        self.session.headers.update({ 'X-API-Key': api_key, 'X-API-Secret': api_secret, 'Content-Type': 'application/json' })
    
    def _request(self, endpoint: str, method: str = 'GET', data: Dict = None) -> Dict:
        url = f"{self.base_url}{endpoint}"
        try:
            response = self.session.request(method, url, json=data, timeout=30)
            response.raise_for_status()
            result = response.json()
            if not result.get('success'): raise Exception(result.get('error', 'Erro desconhecido'))
            return result.get('data', result)
        except requests.exceptions.RequestException as e: raise Exception(f"Erro na requisição: {str(e)}")
    
    def get_balance(self) -> Dict: return self._request('/balance')
    def get_services(self, country: str = None, service: str = None, operator: str = None, available: bool = None) -> Dict:
        params = {}
        if country: params['country'] = country
        if service: params['service'] = service
        if operator: params['operator'] = operator
        if available: params['available'] = 'true'
        query = '&'.join([f"{k}={v}" for k, v in params.items()])
        endpoint = f"/services?{query}" if query else "/services"
        return self._request(endpoint)
    def buy_number(self, service: str, country: str, operator: str = None, max_price: float = None, request_id: str = None) -> Dict:
        data = { 'service': service, 'country': country }
        if operator: data['operator'] = operator
        if max_price: data['max_price'] = max_price
        if request_id: data['request_id'] = request_id
        return self._request('/buy', 'POST', data)
    def check_status(self, activation_id: str) -> Dict: return self._request(f"/status?activation_id={activation_id}")
    def cancel_activation(self, activation_id: str) -> Dict: return self._request('/cancel', 'POST', {'activation_id': activation_id})
    def register_webhook(self, event: str, url: str, secret: str = None) -> Dict:
        data = {'event': event, 'url': url}
        if secret: data['secret'] = secret
        return self._request('/webhook', 'POST', data)
    def list_webhooks(self) -> Dict: return self._request('/webhook')
    def delete_webhook(self, webhook_id: int) -> Dict: return self._request('/webhook', 'DELETE', {'webhook_id': webhook_id})

if __name__ == '__main__':
    try:
        client = SMSProviderClient('sua_api_key', 'seu_api_secret')
        balance = client.get_balance()
        print(f"Saldo disponível: R$ {balance['available']:.2f}")
        services = client.get_services(country='73', available=True)
        for country in services:
            print(f"\nPaís: {country['country_name']}")
            for service in country['services']:
                print(f"  - {service['name']}: R$ {service['price']:.2f} (estoque: {service['stock']})")
    except Exception as e: print(f"Erro: {e}")

Node.js - Cliente completo


const axios = require('axios');

class SMSProviderClient {
    constructor(apiKey, apiSecret, baseUrl = 'https://master-sms.shop/api/v1') {
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        this.baseUrl = baseUrl.replace(/\/$/, '');
        this.client = axios.create({
            baseURL: this.baseUrl,
            timeout: 30000,
            headers: { 'X-API-Key': apiKey, 'X-API-Secret': apiSecret, 'Content-Type': 'application/json' }
        });
    }
    
    async _request(endpoint, method = 'GET', data = null) {
        try {
            const response = await this.client.request({ url: endpoint, method, data });
            if (!response.data.success) throw new Error(response.data.error || 'Erro desconhecido');
            return response.data.data || response.data;
        } catch (error) {
            if (error.response) throw new Error(error.response.data.error || `HTTP ${error.response.status}`);
            throw error;
        }
    }
    
    async getBalance() { return this._request('/balance'); }
    async getServices(filters = {}) {
        const params = new URLSearchParams(filters).toString();
        const endpoint = params ? `/services?${params}` : '/services';
        return this._request(endpoint);
    }
    async buyNumber(service, country, operator = null, maxPrice = null, requestId = null) {
        const data = { service, country };
        if (operator) data.operator = operator;
        if (maxPrice) data.max_price = maxPrice;
        if (requestId) data.request_id = requestId;
        return this._request('/buy', 'POST', data);
    }
    async checkStatus(activationId) { return this._request(`/status?activation_id=${encodeURIComponent(activationId)}`); }
    async cancelActivation(activationId) { return this._request('/cancel', 'POST', { activation_id: activationId }); }
    async registerWebhook(event, url, secret = null) {
        const data = { event, url };
        if (secret) data.secret = secret;
        return this._request('/webhook', 'POST', data);
    }
    async listWebhooks() { return this._request('/webhook'); }
    async deleteWebhook(webhookId) { return this._request('/webhook', 'DELETE', { webhook_id: webhookId }); }
}

async function main() {
    try {
        const client = new SMSProviderClient('sua_api_key', 'seu_api_secret');
        const balance = await client.getBalance();
        console.log(`Saldo disponível: R$ ${balance.available.toFixed(2)}`);
        const services = await client.getServices({ country: '73', available: true });
        services.forEach(country => {
            console.log(`\nPaís: ${country.country_name}`);
            country.services.forEach(service => {
                console.log(`  - ${service.name}: R$ ${service.price.toFixed(2)} (estoque: ${service.stock})`);
            });
        });
    } catch (error) { console.error('Erro:', error.message); }
}
main();

cURL - Exemplos práticos


#!/bin/bash
API_KEY="sua_api_key"
API_SECRET="seu_api_secret"
BASE_URL="https://master-sms.shop/api/v1"

echo "📊 Consultando saldo..."
curl -s -X GET "$BASE_URL/balance" -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" | jq '.'

echo -e "\n📋 Listando serviços do Brasil..."
curl -s -X GET "$BASE_URL/services?country=73&available=true" -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" | jq '.'

echo -e "\n🛒 Comprando número WhatsApp..."
REQUEST_ID="req_$(date +%s)"
curl -s -X POST "$BASE_URL/buy" -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" -H "Content-Type: application/json" -d "{\"service\":\"wa\",\"country\":\"73\",\"operator\":\"claro\",\"max_price\":5.00,\"request_id\":\"$REQUEST_ID\"}" | jq '.'

ACTIVATION_ID="ACT123456"
echo -e "\n🔍 Verificando status..."
curl -s -X GET "$BASE_URL/status?activation_id=$ACTIVATION_ID" -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" | jq '.'

echo -e "\n🔔 Registrando webhook..."
curl -s -X POST "$BASE_URL/webhook" -H "X-API-Key: $API_KEY" -H "X-API-Secret: $API_SECRET" -H "Content-Type: application/json" -d '{"event":"sms.received","url":"https://meu-site.com/webhook/sms","secret":"meu_secret_123"}' | jq '.'

JavaScript (Browser/React) - Cliente


class SMSProviderClient {
    constructor(apiKey, apiSecret, baseUrl = 'https://master-sms.shop/api/v1') {
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        this.baseUrl = baseUrl.replace(/\/$/, '');
    }
    
    async request(endpoint, method = 'GET', data = null) {
        const url = `${this.baseUrl}${endpoint}`;
        const headers = { 'X-API-Key': this.apiKey, 'X-API-Secret': this.apiSecret, 'Content-Type': 'application/json' };
        const options = { method, headers, mode: 'cors' };
        if (data) options.body = JSON.stringify(data);
        const response = await fetch(url, options);
        const result = await response.json();
        if (!response.ok || !result.success) throw new Error(result.error || `HTTP ${response.status}`);
        return result.data || result;
    }
    
    async getBalance() { return this.request('/balance'); }
    async getServices(filters = {}) {
        const params = new URLSearchParams(filters).toString();
        const endpoint = params ? `/services?${params}` : '/services';
        return this.request(endpoint);
    }
    async buyNumber(service, country, operator = null, maxPrice = null, requestId = null) {
        const data = { service, country };
        if (operator) data.operator = operator;
        if (maxPrice) data.max_price = maxPrice;
        if (requestId) data.request_id = requestId;
        return this.request('/buy', 'POST', data);
    }
    async checkStatus(activationId) { return this.request(`/status?activation_id=${encodeURIComponent(activationId)}`); }
    async cancelActivation(activationId) { return this.request('/cancel', 'POST', { activation_id: activationId }); }
}

async function exemplo() {
    try {
        const client = new SMSProviderClient('sua_api_key', 'seu_api_secret');
        const balance = await client.getBalance();
        console.log('Saldo:', balance);
        const services = await client.getServices({ country: '73' });
        console.log('Serviços:', services);
    } catch (error) { console.error('Erro:', error.message); }
}

Códigos de Erro

CódigoSignificadoDescriçãoSolução
400Bad RequestParâmetros inválidos ou ausentesVerifique os campos obrigatórios
401UnauthorizedAPI Key ou Secret inválidosVerifique suas credenciais
402Payment RequiredSaldo insuficienteRecarregue sua conta
403ForbiddenSem permissão para o recursoVerifique as permissões da chave
404Not FoundRecurso não encontradoVerifique o endpoint e parâmetros
405Method Not AllowedMétodo HTTP inválidoUse GET/POST conforme documentado
409ConflictRequest ID já utilizadoUse um request_id único
429Too Many RequestsLimite de requisições excedidoAguarde e reduza a frequência
500Internal Server ErrorErro interno do servidorTente novamente ou contate o suporte

Rate Limiting

Cada chave de API tem um limite de requisições por minuto (configurável no painel).

Os headers de resposta incluem informações sobre o rate limit:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1704067260

Segurança de Webhooks

Para garantir que os webhooks são realmente enviados por nossa API, você pode verificar a assinatura:

Verificação da assinatura (PHP):


$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'seu_secret_configurado';
$expected = hash_hmac('sha256', $payload, $secret);
if (hash_equals($expected, $signature)) {
    $data = json_decode($payload, true);
} else {
    http_response_code(401);
    exit;
}
Gerenciar Chaves