Master sms Master sms API
Manage keys
Official API documentation

Master sms API

Integrate virtual numbers and SMS reception into your system with a secure and predictable API.

Version 4.2.0 REST · JSON · HTTPS Language: English

Overview

Base URL

All routes below use this base URL and return UTF-8 JSON.

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

Quick start

Create a key in the dashboard, keep the secret server-side only, and make your first balance request.

Manage keys
Use the API Secret only on the backend. Never place credentials in a browser, distributed application, or public repository.

Authentication

Send both credentials on every protected route.

Headers

Accept: application/json
Content-Type: application/json
X-API-Key: your_api_key
X-API-Secret: your_api_secret

Response format

Success responses return success=true and data. Errors return success=false, error, and the corresponding HTTP status.

{
    "success": true,
    "data": {
        "example": "value"
    },
    "timestamp": 1785078000
}
{
    "success": false,
    "error": "Error description",
    "code": 400
}

Endpoint reference

The routes documented below match the public API v1 front controller.

GET /health Public route

API health

Confirms that the API is operational and returns its version.

Response example

{
    "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
}
GET /balance Authentication required

Get balance

Returns the account total, blocked and available balance, plus currency.

Response example

{
    "success": true,
    "data": {
        "balance": 1250.5,
        "blocked": 50,
        "available": 1200.5,
        "currency": "BRL",
        "limit": 0
    },
    "timestamp": 1785078000
}
GET /services Authentication required

List services

Lists countries, services, operators, providers, calculated prices, and stock.

Optional filters

ParameterTypeDescriptionExample
countrystringNumeric country code.73
servicestringService code, for example wa.wa
operatorstringSpecific operator. It may also be a provider-supported list.claro
availablebooleanWhen true, returns only items in stock.true
providerstringProvider name or identifier.Hero SMS
searchstringText search by service.WhatsApp

Request example

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

Response example

{
    "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
}
POST /buy Authentication required

Buy number

Purchases a virtual number and creates an SMS activation.

JSON body

FieldTypeRequiredDescription
servicestringYesService code, for example wa.
countrystringYesNumeric country code.
request_idstringYesUnique purchase-attempt identifier used to prevent duplicates.
operatorstringNoSpecific operator. It may also be a provider-supported list.
providerstringNoProvider name or identifier.
max_pricenumberNoMaximum accepted price in the currency returned by the API.
request_id: Generate a new request_id per purchase intent and reuse the same value only when retrying that same intent after a network failure.
max_price: The purchase fails before charging when the calculated price exceeds max_price.

Request example

{
    "service": "wa",
    "country": "73",
    "operator": "claro",
    "provider": "Hero SMS",
    "max_price": 5,
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Response example

{
    "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
}
GET /status?activation_id={id} Authentication required

Get activation

Refreshes and returns an activation status, number, and SMS code.

ParameterRequiredDescription
activation_idYesID returned by the purchase.

Possible statuses

StatusDescription
pendingWaiting for SMS.
receivedSMS received; code contains the code.
canceledActivation canceled.
expiredActivation expired.

Response example

{
    "success": true,
    "data": {
        "activation_id": "ACT17850780001234",
        "status": "received",
        "phone": "5511999999999",
        "created_at": 1785078000,
        "code": "123456",
        "received_at": 1785078060
    },
    "timestamp": 1785078060
}
POST /cancel Authentication required

Cancel activation

Cancels an eligible activation and reports the refund.

Cancellation depends on minimum time, activation status, and provider rules. Activations that have received an SMS cannot be canceled.

JSON body

{ "activation_id": "ACT17850780001234" }

Response example

{
    "success": true,
    "data": {
        "activation_id": "ACT17850780001234",
        "status": "canceled",
        "refunded": true,
        "refund_amount": 2.5
    },
    "timestamp": 1785078300
}
POST GET DELETE /webhook Authentication required

Webhooks

Registers, lists, and removes destinations for asynchronous events.

Available events

EventDescription
sms.receivedSMS received.
sms.purchasedNumber purchased.
sms.statusActivation status changed.
balance.lowBalance below the configured threshold.

POST /webhook · JSON body

FieldRequiredDescription
eventYesSigned event name.
urlYesPublic HTTPS URL that receives a JSON POST.
secretNoSecret used to create the HMAC SHA-256 signature.
{
    "event": "sms.received",
    "url": "https://example.com/webhooks/master-sms",
    "secret": "replace_with_a_random_secret"
}

GET /webhook

The list response never returns the stored secret.

DELETE /webhook · JSON body

{ "webhook_id": 1 }

Webhook payload

{
    "event": "sms.received",
    "timestamp": 1785078060,
    "data": {
        "activation_id": "ACT17850780001234",
        "code": "123456",
        "phone": "5511999999999",
        "service": "wa",
        "received_at": 1785078060
    },
    "signature": "legacy_body_signature"
}
GET /stats Authentication required

Statistics

Returns the user totals for purchases, received messages, cancellations, spending, and refunds.

{
    "success": true,
    "data": {
        "total_compras": 42,
        "total_recebidos": 31,
        "total_cancelados": 11,
        "total_gasto": 79.5,
        "total_estornado": 21
    },
    "timestamp": 1785078000
}
GET /commissions Authentication required

Commissions

Returns pending and paid commissions plus the authenticated reseller history.

{
    "success": true,
    "data": {
        "pending_total": 15.3,
        "paid_total": 120,
        "commissions": []
    },
    "timestamp": 1785078000
}

Webhook security

The raw body is signed with HMAC SHA-256. Compare X-Webhook-Signature in constant time before processing JSON.

Return HTTP 2xx quickly. Failed deliveries are retried by the queue with progressive delays.
$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);

Integration examples

Minimal backend clients. Adapt timeouts, logging, and secret storage to your environment.

<?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)),
]);

AI integration prompt

Copy this prompt, provide your stack, and send it to a coding AI. Replace only placeholders; never paste your API Secret into the conversation.

Errors and handling

CodeMeaningRecommended handling
400Bad requestFix JSON, required fields, or operation rules.
401UnauthenticatedCheck X-API-Key and X-API-Secret.
402Insufficient balanceTop up the account before purchasing.
403ForbiddenEnable the key permission or check the IP whitelist.
404Not foundCheck the route, service, stock, or activation_id.
405Invalid methodUse the documented HTTP method.
409Idempotency conflictDo not reuse request_id for another purchase.
429Rate limit exceededWait and retry with backoff.
500Internal errorRecord the request_id and retry without duplicating the purchase.

Rate limit

The per-minute limit depends on the key and is returned in X-RateLimit-Limit. On HTTP 429, use exponential backoff with jitter.

Security checklist

  1. Store the API Key and Secret in environment variables or a secret vault.
  2. Call the API only from your backend; apps and browsers should call your own server.
  3. Use HTTPS, timeouts, credential-free logs, and strict JSON validation.
  4. Use an idempotent request_id and never retry a timed-out purchase with a different identifier.
  5. Validate the webhook signature over the raw body before changing balance or state.