MarioSMS

Receive SMS Codes in PHP: MarioSMS API Tutorial

Updated · MarioSMS team

PHP still runs a huge share of the automation scripts in this niche, so here is the full MarioSMS loop in plain PHP: rent a number, poll until the code arrives, cancel if you change your mind. Everything uses the built-in cURL extension; no Composer packages required, though the same calls drop into Guzzle in the obvious way.

You need a MarioSMS account with balance and your API key from the app profile. Full endpoint reference: app.mariosms.com/api-docs. Authentication is one header: X-API-Key.

A minimal client

<?php

const BASE = 'https://app.mariosms.com/api/v1';
const KEY  = 'your_api_key_here';

function api(string $method, string $path, ?array $body = null): array
{
    $ch = curl_init(BASE . $path);
    $headers = ['X-API-Key: ' . KEY];
    if ($body !== null) {
        $headers[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 15,
    ]);
    $raw    = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    if ($raw === false || $status >= 400) {
        throw new RuntimeException("MarioSMS API error $status: $raw");
    }
    return json_decode($raw, true);
}

Sanity-check the key:

print_r(api('GET', '/balance')); // ['balance' => 100.0]

Rent a number

$activation = api('POST', '/activation', [
    'country' => 'us',
    'service' => 'tg', // Telegram
]);
echo $activation['phone'], PHP_EOL; // e.g. 12025551234

Service and country codes come from GET /services and GET /countries; live prices from GET /prices.

Poll for the code

Enter the number in the service you’re verifying, then poll until the status flips to received:

function waitForCode(string $id, int $timeoutSeconds = 300): ?string
{
    $deadline = time() + $timeoutSeconds;
    while (time() < $deadline) {
        $a = api('GET', "/activation/$id");
        if ($a['status'] === 'received') {
            return $a['smsCode']; // full text in $a['smsText']
        }
        sleep(5);
    }
    return null;
}

echo 'OTP: ', waitForCode($activation['id']), PHP_EOL;

Cancel and refund

Before an SMS arrives, cancelling refunds the full price to your balance:

print_r(api('POST', "/activation/{$activation['id']}/cancel"));
// ['message' => 'activation cancelled', 'refund' => 1.32]

A crashed script costs nothing either: activations that expire without an SMS are cancelled and refunded by the platform automatically.

Notes

  • Keep the API key in an environment variable in real code, not a constant.
  • One activation is one number for one verification; a second service means a second activation.
  • The API also exposes a compatibility endpoint speaking the classic handler_api.php protocol, so legacy PHP scripts written for other providers usually migrate with a base-URL change.
  • Automate what you’re allowed to automate (QA, testing, legitimate accounts) per the acceptable use policy.