Receive SMS Codes in PHP: MarioSMS API Tutorial
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.phpprotocol, 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.