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. | — |
Cancel, resend SMS and finish buttons depend on the number and service: check the can_cancel, can_retry and can_finish fields in the response. If cancel_in > 0, you must wait that many seconds before cancelling.
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
Stokta numarası bulunan servisler, en düşük fiyat ve toplam stokla.
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). |
| servers | integer | optional | If set to 1 (service and country must both be given), the price, stock and success rate of each "Server N" are also returned in the "servers" array. Pass that number as the server parameter when buying. |
curl "https://codesms.org/api/v1/prices?service=tg&country=tr&servers=1" \
-H "X-API-Key: YOUR_API_KEY"$ch = curl_init('https://codesms.org/api/v1/prices?service=tg&country=tr&servers=1');
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&servers=1",
headers={"X-API-Key": "YOUR_API_KEY"}
)
print(response.json())const response = await fetch("https://codesms.org/api/v1/prices?service=tg&country=tr&servers=1", {
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&servers=1", 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&servers=1");
Console.WriteLine(await response.Content.ReadAsStringAsync());HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://codesms.org/api/v1/prices?service=tg&country=tr&servers=1"))
.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&servers=1")
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,
"success_rate": 87,
"servers": [
{
"server": 3,
"price": 8.5,
"stock": 300,
"success_rate": 91
},
{
"server": 7,
"price": 9.2,
"stock": 120,
"success_rate": null
}
]
}
]
}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). |
| max_price | number | optional | The highest price (TRY) you accept. If omitted, the lowest listed price applies; if the price would exceed it, PRICE_CHANGED is returned. |
| server | integer | optional | Buy only from this "Server N" (GET /api/v1/prices?servers=1). When given, no other server is tried; NO_NUMBERS is returned if it has none, PRICE_CHANGED if its price exceeds max_price. If omitted, all servers are tried in price order. |
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"
},
"server": 3,
"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"
},
"server": 3,
"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"
},
"server": 3,
"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"
},
"server": 3,
"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"
},
"server": 3,
"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"
},
"server": 3,
"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.
- operator: only a numeric value is interpreted as the "Server N" number (GET /api/v1/prices?servers=1); if omitted, all servers are tried in price order.
| action | Parameters | Example response |
|---|---|---|
| getBalance | — | ACCESS_BALANCE:125.50 |
| getNumber | service, country (ID), [maxPrice], [operator = Server no] | ACCESS_NUMBER:1234:905551234567 |
| getNumberV2 | service, country (ID), [maxPrice], [operator = Server no] | {"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). |
| BAD_MAX_PRICE | 400 | max_price must be a positive number. |
| BAD_SERVER | 400 | server must be a positive integer (the Server number). |
| PRICE_CHANGED | 409 | No numbers are left at the price you accepted; you were not charged. error.price in the response is the current price; if you accept it, repeat the same request with max_price. |
| 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.
- The price may change with stock: if no numbers are left at the listed price you are not charged and the current price is reported with PRICE_CHANGED (WRONG_MAX_PRICE:price on the SMS-Activate compatible endpoint). If you accept it, repeat the request with max_price (maxPrice).
- The success_rate field in the price list is the percentage of sales in the last 30 days for that service and country where an SMS code arrived; it is null when the sample is too small.