API Documentation
REST API v1 and SMS-Activate compatible endpoints
Introduction
The API lets you buy virtual numbers with your account balance, read incoming SMS codes and cancel for a refund. All requests use HTTPS; responses are JSON.
- Base URL
https://codesms.org- Format
- JSON (
application/json) — form-encoded is accepted too - Currency
- TRY (₺)
- Successful response
{"success": true, "data": ...}- Error response
{"success": false, "error": {"code": "NO_BALANCE", "message": "..."}}
Authentication
Send your API key with every request. You can get the key on the API page in your panel.
curl "https://codesms.org/api/v1/balance" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/balance');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY']]);requests.get("https://codesms.org/api/v1/balance", headers={"X-API-Key": "YOUR_API_KEY"})fetch("https://codesms.org/api/v1/balance", { headers: { "X-API-Key": "YOUR_API_KEY" } })Alternatives: the Authorization: Bearer YOUR_API_KEY header or the ?api_key=YOUR_API_KEY query parameter (for testing only; the key may end up in logs).
- The API does not work on accounts with an unverified e-mail (EMAIL_NOT_VERIFIED).
- You can define an allowed IP list in the panel; if the list is set, requests are accepted only from those addresses.
- If your key leaks, regenerate it in the panel right away; the old key becomes invalid instantly.
Quick start
Buy a number → wait for the code → finish. If no code arrives, cancel to get a refund.
<?php
$base = 'https://codesms.org';
$key = 'YOUR_API_KEY';
function api($method, $path, $body = null) {
global $base, $key;
$ch = curl_init($base . $path);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . $key, 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body ? json_encode($body) : null]);
return json_decode(curl_exec($ch), true);
}
$r = api('POST', '/api/v1/activations', ['service' => 'tg', 'country' => 'tr']);
if (!$r['success']) { exit('Hata: ' . $r['error']['code']); }
$id = $r['data']['id'];
echo "Numara: {$r['data']['phone']}\n";
for ($i = 0; $i < 120; $i++) { // en fazla ~6 dk
sleep(3);
$s = api('GET', "/api/v1/activations/$id")['data'];
if ($s['status'] === 'received') { echo "Kod: {$s['code']}\n"; api('POST', "/api/v1/activations/$id/finish"); exit; }
if (in_array($s['status'], ['canceled', 'expired', 'failed'])) exit("Bitti: {$s['status']}\n");
}
api('POST', "/api/v1/activations/$id/cancel"); // kod gelmedi: iptal et, ücret iadeimport time, requests
BASE = "https://codesms.org"
HEAD = {"X-API-Key": "YOUR_API_KEY"}
r = requests.post(f"{BASE}/api/v1/activations", headers=HEAD, json={"service": "tg", "country": "tr"}).json()
if not r["success"]:
raise SystemExit(f"Hata: {r['error']['code']}")
act = r["data"]
print("Numara:", act["phone"])
for _ in range(120): # en fazla ~6 dk
time.sleep(3)
s = requests.get(f"{BASE}/api/v1/activations/{act['id']}", headers=HEAD).json()["data"]
if s["status"] == "received":
print("Kod:", s["code"])
requests.post(f"{BASE}/api/v1/activations/{act['id']}/finish", headers=HEAD)
break
if s["status"] in ("canceled", "expired", "failed"):
break
else:
requests.post(f"{BASE}/api/v1/activations/{act['id']}/cancel", headers=HEAD) # ücret iadeconst BASE = "https://codesms.org";
const HEAD = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };
const api = (method, path, body) => fetch(BASE + path, { method, headers: HEAD, body: body && JSON.stringify(body) }).then(r => r.json());
const r = await api("POST", "/api/v1/activations", { service: "tg", country: "tr" });
if (!r.success) throw new Error(r.error.code);
const { id, phone } = r.data;
console.log("Numara:", phone);
for (let i = 0; i < 120; i++) { // en fazla ~6 dk
await new Promise(res => setTimeout(res, 3000));
const s = (await api("GET", `/api/v1/activations/${id}`)).data;
if (s.status === "received") { console.log("Kod:", s.code); await api("POST", `/api/v1/activations/${id}/finish`); process.exit(0); }
if (["canceled", "expired", "failed"].includes(s.status)) process.exit(1);
}
await api("POST", `/api/v1/activations/${id}/cancel`); // ücret iadeActivation lifecycle
| status | Meaning | Possible actions |
|---|---|---|
waiting | Number issued, waiting for SMS. | Poll, cancel (if can_cancel=true). |
received | SMS arrived; in the code field. | Use the code, finish; request another SMS if can_retry=true. |
completed | Completed (code used). | — |
canceled | Canceled, refunded. | — |
expired | Time expired, no SMS; refunded. | — |
failed | Could not get a number; refunded. | — |
The availability of cancel, another SMS and finish depends on the provider: check the can_cancel, can_retry and can_finish fields in the response. If cancel_in > 0 you must wait that many seconds before canceling.
Get balance
Returns the current balance of your account.
curl "https://codesms.org/api/v1/balance" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/balance');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/balance",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/balance", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/balance", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/balance");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/balance"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/balance")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"balance": 125.5,
"currency": "TRY"
}
}List services
Services that have numbers in stock, with the lowest price (your tier discount applied) and total stock.
curl "https://codesms.org/api/v1/services" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/services');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/services",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/services", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/services", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/services");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/services"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/services")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": [
{
"code": "tg",
"slug": "telegram",
"name": "Telegram",
"min_price": 2.1,
"stock": 18540
}
]
}List countries
Countries that have numbers in stock. "id" is the SMS-Activate compatible numeric country code.
curl "https://codesms.org/api/v1/countries" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/countries');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/countries",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/countries", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/countries", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/countries");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/countries"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/countries")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": [
{
"iso": "tr",
"id": 62,
"name": "Turkey",
"name_tr": "Türkiye",
"dial": "90"
}
]
}Price and stock
Current price and stock per service/country. An unfiltered call returns the whole list (up to 20,000 rows).
| Parameter | Type | Description | |
|---|---|---|---|
| service | string | optional | Service code or slug (e.g. tg). |
| country | string | optional | Country ISO code (tr) or numeric ID (62). |
curl "https://codesms.org/api/v1/prices?service=tg&country=tr" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/prices?service=tg&country=tr');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/prices?service=tg&country=tr",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/prices?service=tg&country=tr", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/prices?service=tg&country=tr", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/prices?service=tg&country=tr");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/prices?service=tg&country=tr"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/prices?service=tg&country=tr")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": [
{
"service": "tg",
"country": "tr",
"price": 8.5,
"currency": "TRY",
"stock": 420
}
]
}Buy a number
Opens a new activation (number), deducting from your balance. Returns NO_BALANCE if the balance is insufficient, NO_NUMBERS if there is no stock. If no SMS arrives or you cancel, the fee is refunded automatically. Recommended: send a unique Idempotency-Key header with every purchase; if you retry with the same key after a network error, no second number is bought and the first activation is returned (valid for 24 hours).
| Parameter | Type | Description | |
|---|---|---|---|
| service | string | required | Service code or slug (e.g. tg). |
| country | string | required | Country ISO code (tr) or numeric ID (62). |
curl -X POST "https://codesms.org/api/v1/activations" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"service":"tg","country":"tr"}'$ch = curl_init('https://codesms.org/api/v1/activations');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode(['service' => 'tg', 'country' => 'tr']),
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.post(
"https://codesms.org/api/v1/activations",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"service": "tg", "country": "tr"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({"service":"tg","country":"tr"})
});
console.log(await response.json());package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://codesms.org/api/v1/activations", bytes.NewBufferString(`{"service":"tg","country":"tr"}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.PostAsync("https://codesms.org/api/v1/activations", new StringContent("{\"service\":\"tg\",\"country\":\"tr\"}", System.Text.Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"service\":\"tg\",\"country\":\"tr\"}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations")
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
req['Content-Type'] = 'application/json'
req.body = '{"service":"tg","country":"tr"}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"id": 1234,
"status": "waiting",
"phone": "+905551234567",
"code": null,
"text": null,
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"retry_count": 0,
"can_cancel": true,
"can_retry": false,
"can_finish": false,
"cancel_in": 0
}
}Activation status / SMS code
Returns the activation status and the SMS code if it arrived. Poll every 3–5 seconds until the code arrives (not needed if you use webhooks).
| Parameter | Type | Description | |
|---|---|---|---|
| id | integer | required | Activation ID (path parameter). |
curl "https://codesms.org/api/v1/activations/1234" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/activations/1234');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/activations/1234",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations/1234", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/activations/1234", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/activations/1234");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations/1234"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations/1234")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"status": "received",
"code": "482913",
"text": "Your Telegram code: 482913",
"can_cancel": false,
"can_retry": true,
"can_finish": true,
"id": 1234,
"phone": "+905551234567",
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"retry_count": 0,
"cancel_in": 0
}
}List activations
Your latest activations (newest first).
| Parameter | Type | Description | |
|---|---|---|---|
| status | string | optional | waiting, received, completed, canceled, expired, failed |
| limit | integer | optional | 1–100 (default 30). |
curl "https://codesms.org/api/v1/activations?status=waiting&limit=20" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/activations?status=waiting&limit=20');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/api/v1/activations?status=waiting&limit=20",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations?status=waiting&limit=20", {
method: "GET",
headers: {
"X-API-Key": "YOUR_API_KEY"
}
});
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://codesms.org/api/v1/activations?status=waiting&limit=20", nil)
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.GetAsync("https://codesms.org/api/v1/activations?status=waiting&limit=20");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations?status=waiting&limit=20"))
.header("X-API-Key", "YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations?status=waiting&limit=20")
req = Net::HTTP::Get.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": [
{
"id": 1234,
"status": "waiting",
"phone": "+905551234567",
"code": null,
"text": null,
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"retry_count": 0,
"can_cancel": true,
"can_retry": false,
"can_finish": false,
"cancel_in": 0
}
]
}Cancel and get a refund
If no code arrived, cancels the activation and refunds the fee to your balance. Some providers do not allow cancellation in the first seconds (CANCEL_TOO_EARLY is returned while cancel_in > 0). If the provider does not support it, can_cancel=false.
| Parameter | Type | Description | |
|---|---|---|---|
| id | integer | required | Activation ID (path parameter). |
curl -X POST "https://codesms.org/api/v1/activations/1234/cancel" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'$ch = curl_init('https://codesms.org/api/v1/activations/1234/cancel');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([]),
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.post(
"https://codesms.org/api/v1/activations/1234/cancel",
headers={"X-API-Key": "YOUR_API_KEY"},
json={}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations/1234/cancel", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({})
});
console.log(await response.json());package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://codesms.org/api/v1/activations/1234/cancel", bytes.NewBufferString(`{}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.PostAsync("https://codesms.org/api/v1/activations/1234/cancel", new StringContent("{}", System.Text.Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations/1234/cancel"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations/1234/cancel")
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
req['Content-Type'] = 'application/json'
req.body = '{}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"status": "canceled",
"can_cancel": false,
"id": 1234,
"phone": "+905551234567",
"code": null,
"text": null,
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"retry_count": 0,
"can_retry": false,
"can_finish": false,
"cancel_in": 0
}
}Request another SMS
Requests a new SMS to the same number after a code arrived (only when can_retry=true). The activation goes back to "waiting".
| Parameter | Type | Description | |
|---|---|---|---|
| id | integer | required | Activation ID (path parameter). |
curl -X POST "https://codesms.org/api/v1/activations/1234/retry" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'$ch = curl_init('https://codesms.org/api/v1/activations/1234/retry');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([]),
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.post(
"https://codesms.org/api/v1/activations/1234/retry",
headers={"X-API-Key": "YOUR_API_KEY"},
json={}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations/1234/retry", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({})
});
console.log(await response.json());package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://codesms.org/api/v1/activations/1234/retry", bytes.NewBufferString(`{}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.PostAsync("https://codesms.org/api/v1/activations/1234/retry", new StringContent("{}", System.Text.Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations/1234/retry"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations/1234/retry")
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
req['Content-Type'] = 'application/json'
req.body = '{}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"retry_count": 1,
"id": 1234,
"status": "waiting",
"phone": "+905551234567",
"code": null,
"text": null,
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"can_cancel": true,
"can_retry": false,
"can_finish": false,
"cancel_in": 0
}
}Finish
Reports that you used the code successfully and closes the activation. Activations not finished within 15 minutes are finished automatically.
| Parameter | Type | Description | |
|---|---|---|---|
| id | integer | required | Activation ID (path parameter). |
curl -X POST "https://codesms.org/api/v1/activations/1234/finish" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'$ch = curl_init('https://codesms.org/api/v1/activations/1234/finish');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([]),
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.post(
"https://codesms.org/api/v1/activations/1234/finish",
headers={"X-API-Key": "YOUR_API_KEY"},
json={}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/activations/1234/finish", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({})
});
console.log(await response.json());package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("POST", "https://codesms.org/api/v1/activations/1234/finish", bytes.NewBufferString(`{}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}using var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var response = await client.PostAsync("https://codesms.org/api/v1/activations/1234/finish", new StringContent("{}", System.Text.Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/activations/1234/finish"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'net/http'
require 'json'
uri = URI("https://codesms.org/api/v1/activations/1234/finish")
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = 'YOUR_API_KEY'
req['Content-Type'] = 'application/json'
req.body = '{}'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(req) }
puts res.body{
"success": true,
"data": {
"status": "completed",
"code": "482913",
"text": "Your Telegram code: 482913",
"can_cancel": false,
"can_retry": true,
"can_finish": true,
"id": 1234,
"phone": "+905551234567",
"service": {
"code": "tg",
"name": "Telegram"
},
"country": {
"iso": "tr",
"name": "Turkey",
"dial": "90"
},
"price": 8.5,
"currency": "TRY",
"created_at": "2026-01-15T10:00:00+03:00",
"expires_at": "2026-01-15T10:20:00+03:00",
"retry_count": 0,
"cancel_in": 0
}
}Webhook
If you set a webhook URL in the panel, we send a signed POST request to it when the SMS code arrives; no need to poll constantly. On non-2xx responses it is retried after 1 min, 5 min, 15 min, 1 h and 6 h.
- X-SMSOnay-Event
activation.code- X-SMSOnay-Timestamp
- Unix seconds
- X-SMSOnay-Signature
sha256=HMAC_SHA256(secret, timestamp + "." + body)
{
"event": "activation.code",
"activation": {
"id": 1234,
"status": "received",
"phone": "+905551234567",
"code": "482913",
"service": {
"code": "tg"
},
"...": "..."
},
"timestamp": 1768460000
}# HMAC-SHA256(secret, timestamp + "." + rawBody) -> "sha256=" + hex
# Header'lar: X-SMSOnay-Timestamp, X-SMSOnay-Signature$ts = $_SERVER['HTTP_X_SMSONAY_TIMESTAMP'];
$sig = $_SERVER['HTTP_X_SMSONAY_SIGNATURE'];
$body = file_get_contents('php://input');
$calc = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, 'whsec_YOUR_SECRET');
if (!hash_equals($calc, $sig) || abs(time() - (int)$ts) > 300) { http_response_code(401); exit; }
$event = json_decode($body, true);import hmac, hashlib, time
def verify(ts, signature, body: bytes, secret: str) -> bool:
calc = 'sha256=' + hmac.new(secret.encode(), ts.encode() + b'.' + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(calc, signature) and abs(time.time() - int(ts)) < 300const crypto = require('crypto');
function verify(ts, signature, rawBody, secret) {
const calc = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(calc), Buffer.from(signature)) && Math.abs(Date.now() / 1000 - Number(ts)) < 300;
}func verify(ts, signature string, body []byte, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts + "."))
mac.Write(body)
calc := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(calc), []byte(signature))
}static bool Verify(string ts, string signature, string body, string secret)
{
using var h = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var calc = "sha256=" + Convert.ToHexString(h.ComputeHash(Encoding.UTF8.GetBytes(ts + "." + body))).ToLower();
return CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(calc), Encoding.UTF8.GetBytes(signature));
}static boolean verify(String ts, String signature, String body, String secret) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String calc = "sha256=" + HexFormat.of().formatHex(mac.doFinal((ts + "." + body).getBytes(StandardCharsets.UTF_8)));
return MessageDigest.isEqual(calc.getBytes(), signature.getBytes());
}require 'openssl'
def verify(ts, signature, body, secret)
calc = 'sha256=' + OpenSSL::HMAC.hexdigest('SHA256', secret, "#{ts}.#{body}")
Rack::Utils.secure_compare(calc, signature)
endYou can get your signing secret on the API page in the panel. Verify the timestamp (±5 min) and the signature; de-duplicate repeated deliveries for the same activation by id.
SMS-Activate compatible API
If your existing registration/automation software supports the SMS-Activate (handler_api) protocol, you can connect to us just by changing the server address and API key.
- service: service code (tg, wa, ig, go, fb …) — the code from GET /api/v1/services.
- country: SMS-Activate country ID (e.g. 62 = Turkey, 0 = Russia, 187 = USA) — the id from GET /api/v1/countries.
- Prices are in Turkish lira; maxPrice is interpreted in TRY too.
| action | Parameters | Example response |
|---|---|---|
| getBalance | — | ACCESS_BALANCE:125.50 |
| getNumber | service, country (ID), [maxPrice] | ACCESS_NUMBER:1234:905551234567 |
| getNumberV2 | service, country (ID), [maxPrice] | {"activationId":"1234","phoneNumber":"905551234567","activationCost":8.5,"countryCode":"62","canGetAnotherSms":true,...} |
| getStatus | id | STATUS_WAIT_CODE | STATUS_OK:482913 | STATUS_WAIT_RETRY:482913 | STATUS_CANCEL |
| getStatusV2 | id | {"verificationType":0,"sms":{"dateTime":"...","code":"482913","text":"..."},"call":null} |
| setStatus | id, status (3=tekrar SMS, 6=tamamla, 8=iptal) | ACCESS_RETRY_GET | ACCESS_ACTIVATION | ACCESS_CANCEL | EARLY_CANCEL_DENIED |
| getPrices | [service], [country] | {"62":{"tg":{"cost":8.5,"count":420}}} |
| getNumbersStatus | country | {"tg_0":420,"wa_0":310} |
| getCountries | — | {"62":{"id":62,"eng":"Turkey",...}} |
| getServicesList | — | {"status":"success","services":[{"code":"tg","name":"Telegram"}]} |
| getActiveActivations | — | {"status":"success","activeActivations":[...]} |
curl "https://codesms.org/stubs/handler_api.php?api_key=YOUR_API_KEY&action=getNumber&service=tg&country=62" \
-H "X-API-Key: unused"$ch = curl_init('https://codesms.org/stubs/handler_api.php?api_key=YOUR_API_KEY&action=getNumber&service=tg&country=62');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: unused'],
]);
$response = json_decode(curl_exec($ch), true);
print_r($response);import requests
response = requests.get(
"https://codesms.org/stubs/handler_api.php?api_key=YOUR_API_KEY&action=getNumber&service=tg&country=62",
headers={"X-API-Key": "unused"}
)
print(response.json())const response = await fetch("https://codesms.org/stubs/handler_api.php?api_key=YOUR_API_KEY&action=getNumber&service=tg&country=62", {
method: "GET",
headers: {
"X-API-Key": "unused"
}
});
console.log(await response.json());Error responses are plain text: BAD_KEY, BAD_ACTION, BAD_SERVICE, NO_NUMBERS, NO_BALANCE, NO_ACTIVATION, EARLY_CANCEL_DENIED, WRONG_MAX_PRICE:price, ACCOUNT_INACTIVE…
Signed requests (optional)
If Panel → API → "Signed request required" is turned on, the following headers must be added to every REST request; even if your key is stolen, requests can't be made without the signing secret, and the same request can't be replayed. The SMS-Activate compatible endpoint doesn't support signing, so it can't be used while this option is on.
X-Timestamp: Unix time (seconds); may differ from the server time by at most 5 minutes.X-Nonce: A new random value for each request, 16–64 characters (A-Z a-z 0-9 _ -).X-Signature:hex(HMAC-SHA256(imza_sırrı, X-Timestamp + "\n" + X-Nonce + "\n" + METHOD + "\n" + yol?sorgu + "\n" + hex(SHA256(gövde))))
$ts = (string)time(); $nonce = bin2hex(random_bytes(16)); $body = json_encode(['service' => 'tg', 'country' => 'tr']);
$sig = hash_hmac('sha256', "$ts\n$nonce\nPOST\n/api/v1/activations\n" . hash('sha256', $body), $signSecret);
// Başlıklar: X-API-Key, X-Timestamp: $ts, X-Nonce: $nonce, X-Signature: $sig, Content-Type: application/jsonError codes
| code | HTTP | Description |
|---|---|---|
| BAD_KEY | 401 | API key is missing or invalid. |
| API_DISABLED | 403 | API access is disabled on your account. |
| EMAIL_NOT_VERIFIED | 403 | Your e-mail address is not verified. |
| IP_NOT_ALLOWED | 403 | The request IP address is not in the allow list. |
| ACCOUNT_BANNED | 403 | The account is suspended. |
| RATE_LIMIT | 429 | The per-minute request limit was exceeded. |
| BAD_SERVICE | 400 | The service code is invalid or missing. |
| BAD_COUNTRY | 400 | The country code is invalid or missing. |
| NO_BALANCE | 402 | Insufficient balance. (There is no minimum balance requirement; this error is returned when your balance is lower than the price.) |
| NO_NUMBERS | 409 | No numbers for this service/country right now (no charge / refunded). |
| TOO_MANY_ACTIVE | 429 | The allowed number of concurrent active activations was exceeded. |
| NOT_FOUND | 404 | Activation not found. |
| BAD_STATUS | 409 | This action is not possible in the current activation state. |
| CANCEL_TOO_EARLY | 409 | The provider does not allow cancellation at this stage; retry after cancel_in seconds. |
| ALREADY_RECEIVED | 409 | Cannot be canceled because the code has arrived. |
| UNSUPPORTED | 409 | The provider does not support this action (e.g. another SMS). |
| PROVIDER_ERROR | 502 | The provider had a temporary error; try again. |
| PLAN_REQUIRED | 403 | API erişimi için etkin bir API paketi gerekiyor (Panel → API). |
| BAD_SIGNATURE | 401 | İmzalı istek zorunlu ve imza eksik/geçersiz ya da zaman damgası 5 dakikadan eski. |
| BAD_IDEMPOTENCY_KEY | 400 | The Idempotency-Key header must be 8–64 characters (letters, digits, _ - : .). |
| IDEMPOTENCY_IN_PROGRESS | 409 | An earlier request with the same Idempotency-Key is still being processed; retry in a few seconds. |
| REPLAYED_REQUEST | 401 | Aynı X-Nonce ikinci kez kullanıldı (tekrar oynatma koruması). |
| SERVER_ERROR | 500 | Unexpected server error. |
Limits and recommendations
- Rate limit: 120 requests per minute (per account).
- Poll status every 3–5 seconds; using webhooks is more efficient.
- Activations that get no SMS are canceled and refunded automatically when time runs out; you can also cancel early.
- The number of simultaneously open activations is limited (TOO_MANY_ACTIVE).
- On a network timeout, resend the purchase request with the same Idempotency-Key header; no second number is bought. If you do not use the header, check your recent activations with GET /api/v1/activations first.