Skip to main content

Buy and Manage Numbers

Order phone numbers for SMS reception and manage active numbers.

Buy a Number

Purchase a phone number to receive SMS codes. The price is immediately deducted from the user's balance and the order starts in waiting status.

Endpoint

POST /api/v1/numbers/

Request Body

{
"provider": "virtual",
"period": "MIN_15",
"service_code": "tg",
"country_code": "2",
"operator_code": "",
"need_fraud_score": false,
"markup_percent": 0,
"promo_code": "DISCOUNT10"
}

Request Fields

FieldTypeRequiredDescription
providerstringYesProvider type: virtual, virtual_rent, residential, residential_rent
periodstringYesRental period (see rules below)
service_codestringYesService code from GET /services/ (e.g. tg, google)
country_codestringYesNumeric country code from GET /countries/
operator_codestringNoMobile operator code from GET /operators/, requested for this exact provider + country_code + service_code (+ period for virtual_rent). Leave it out or send an empty string to have the operator picked automatically. Applies to virtual / virtual_rent only — ignored for residential providers
need_fraud_scorebooleanNoRequest a fraud-score check for the phone number (default false)
markup_percentintegerNoMarkup over base price in %. Allowed: 0, 50, 100, 200, 300, 400, 500, 1000, 2000 (default 0)
promo_codestringNoPromo code to apply a discount to this order

Provider and Period Rules

ProviderAvailable Periods
virtualMIN_15 only
virtual_rentHOUR_4, HOUR_12, DAY, DAY_3, WEEK
residentialMIN_15 only
residential_rentDAY_3, WEEK, WEEK_2, DAY_25

Request Example (Virtual, 15 minutes)

curl -X 'POST' \
'https://app.cyberyozh.com/api/v1/numbers/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"provider": "virtual",
"period": "MIN_15",
"service_code": "tg",
"country_code": "2",
"need_fraud_score": false
}'

Request Example (Virtual Rent, 4 hours)

curl -X 'POST' \
'https://app.cyberyozh.com/api/v1/numbers/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"provider": "virtual_rent",
"period": "HOUR_4",
"service_code": "tg",
"country_code": "1"
}'

Request Example (Virtual, specific operator)

curl -X 'POST' \
'https://app.cyberyozh.com/api/v1/numbers/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here' \
-H 'Content-Type: application/json' \
-d '{
"provider": "virtual",
"period": "MIN_15",
"service_code": "tg",
"country_code": "2",
"operator_code": "beeline"
}'

Success Response (201)

Returns the created order:

{
"id": "71066120515e427ea147fc090fe395ce",
"pk": "71066120-515e-427e-a147-fc090fe395ce",
"provider": "virtual",
"period": "MIN_15",
"service": "tg",
"country": "2",
"operator_code": "beeline",
"operator_name": "Beeline",
"need_fraud_score": false,
"status": "new"
}

The order is created in status new and switches to waiting once the number has been assigned — poll GET /api/v1/numbers/ for the assigned phone_number and the incoming SMS codes.

operator_code / operator_name show the operator the number is actually bought from: the code you passed, or the one picked automatically when you left the field empty. They are null for residential providers.

Error Responses

Rate Limited (429)

{
"detail": "Request was throttled. Expected available in 50 seconds."
}

Insufficient Balance (402)

{
"detail": "You can top up your account balance."
}

Insufficient Stock (400)

{
"count": [
"There are no available phone numbers, try again later!"
]
}

Missing Field (400)

{
"provider": [
"This field is required."
]
}

Bad Service Code (400)

{
"non_field_errors": [
"Bad service_code"
]
}

Bad Operator Code (400)

The operator is not purchasable for this provider + country_code + service_code (+ period). Re-request GET /operators/ for that exact combination and pick a code from the response.

{
"operator_code": [
"Bad operator_code"
]
}

Get Active Numbers

Returns all active phone number orders (status waiting) — orders currently awaiting an SMS code. For completed orders use GET /history/.

Endpoint

GET /api/v1/numbers/

Request

curl -X 'GET' \
'https://app.cyberyozh.com/api/v1/numbers/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Response

[
{
"id": "71066120515e427ea147fc090fe395ce",
"status": "waiting",
"provider": "virtual",
"price_usd": "2.84",
"phone_number": "+15555555555",
"operator_code": "beeline",
"operator_name": "Beeline",
"expiration_time": null,
"history_sms_code": [],
"can_replay": false,
"can_extend": false,
"can_cancel": true
}
]

Response Fields

FieldTypeDescription
idstringOrder UUID
statusstringCurrent order status (waiting)
providerstringProvider type (virtual / virtual_rent / residential / residential_rent)
price_usdstringAmount charged in USD
phone_numberstringAssigned phone number
operator_codestring|nullMobile operator the number was bought from; null for residential providers and for orders created before operator selection existed
operator_namestring|nullHuman-readable name of that operator
expiration_timestring|nullOrder expiration datetime (UTC); null for one-time numbers
history_sms_codearrayList of SMS codes received for this order
can_replaybooleanWhether re-requesting an SMS is currently allowed
can_extendbooleanWhether extending the rental period is currently allowed
can_cancelbooleanWhether cancelling the order is currently allowed

Get Number History

Returns all orders that have reached a terminal state. Active orders (waiting) are excluded — use GET /numbers/ for those.

Orders are sorted by the time they ended, most recent first.

Endpoint

GET /api/v1/numbers/history/

Request

curl -X 'GET' \
'https://app.cyberyozh.com/api/v1/numbers/history/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Response

[
{
"pk": "97f39164-512f-4ccb-9b1a-22cbdee0c47f",
"id": "97f39164-512f-4ccb-9b1a-22cbdee0c47f",
"status": "success",
"provider": "virtual",
"price_usd": "0.15",
"phone_number": "+15555555555",
"operator_code": "beeline",
"operator_name": "Beeline",
"expiration_time": null,
"history_sms_code": ["79373"],
"fraud_score": null,
"expenses": "0.15",
"report": null,
"can_replay": false,
"can_extend": false,
"can_cancel": false
}
]

Possible Statuses

StatusDescription
successSMS code was received
canceledOrder was cancelled by the user
refundOrder was refunded
not_sms_codeNo SMS code arrived within the rental period
calculationOrder is being post-processed / calculated

Cancel a Number

Cancel an active phone number order. The charged amount is refunded to the user's balance. Cancellation is only available within a specific time window and only if no SMS has been received.

Endpoint

PUT /api/v1/numbers/{id}/cancel/

Cancellation Rules by Provider

ProviderWindowCondition
virtual2–15 minutes after purchaseNo SMS received
virtual_rent2–20 minutes after purchaseNo SMS received
residential2–15 minutes after purchaseNo SMS received
residential_rentCannot be cancelled

Request

curl -X 'PUT' \
'https://app.cyberyozh.com/api/v1/numbers/bb157566-8003-49f3-9e74-c1488acb9625/cancel/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Success Response (200)

{
"detail": "Cancel processed"
}

Error Responses

Already Received SMS (400)

{
"detail": "You can't cancel if you've already received a text message."
}

Too Soon — Window Not Opened Yet (400)

{
"detail": "You can cancel the phone number 2 minutes after you bought it."
}

Too Late — Window Expired (400)

{
"detail": "You can cancel the phone number 20 minutes after you bought it."
}

Get Extension Options

Returns the periods an active rental can be extended by, with the price of each extension. Use it to choose the period for Extend a Rental.

Endpoint

GET /api/v1/numbers/{id}/extend-options/

Request

curl -X 'GET' \
'https://app.cyberyozh.com/api/v1/numbers/bb157566-8003-49f3-9e74-c1488acb9625/extend-options/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Success Response (200)

A virtual_rent number bought for a week at 1.50:

{
"options": [
{ "period": "HOUR_4", "price": "0.04", "is_current_period": false },
{ "period": "HOUR_12", "price": "0.11", "is_current_period": false },
{ "period": "DAY", "price": "0.21", "is_current_period": false },
{ "period": "DAY_3", "price": "0.64", "is_current_period": false },
{ "period": "WEEK", "price": "1.50", "is_current_period": true }
]
}

Response Fields

FieldTypeDescription
periodstringPeriod name to pass to the extension
pricestringPrice of the extension in USD
is_current_periodbooleanWhether this is the period the rental was bought with

Pricing Rules

ProviderPeriod the rental was bought withAny other period
virtual_rentPurchase pricePurchase price scaled by hours, rounded to cents, minimum 0.02
residential_rent, residential_privatePurchase priceCurrent retail price of that period; periods without a price are not listed

The list is the provider's extension table and is not checked with the provider in advance. If the provider does not offer a period at the moment, the extension is refused: nothing is charged and the expiration time stays the same.

Error Responses

Number Can't Be Extended (400)

{
"detail": "The number can't be extended."
}

Also returned as "You can only extend an active rental." when the rental is over.

Extend a Rental

Extends an active rental. The chosen period is added to the current expiration time. The extension is processed asynchronously: a 200 response means the request is accepted, not that the rental is already extended. The balance is charged only after the provider confirms the extension.

Endpoint

PUT /api/v1/numbers/{id}/extend/

Request Body

FieldTypeRequiredDescription
periodstringNoPeriod from Get Extension Options. Without it the rental is extended by the period it was bought with

Extension Periods by Provider

ProviderPeriods
virtual_rentHOUR_4, HOUR_12, DAY, DAY_3, WEEK
residential_rentDAY_3, WEEK, WEEK_2, DAY_25
residential_privateMONTH, MONTH_3

One-time numbers (virtual, residential) can't be extended. The price of each period follows the pricing rules.

Request

curl -X 'PUT' \
'https://app.cyberyozh.com/api/v1/numbers/bb157566-8003-49f3-9e74-c1488acb9625/extend/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: your_api_key_here' \
-d '{"period": "DAY"}'

Success Response (200)

{
"detail": "Extend processed",
"period": "DAY",
"price": "0.21"
}

price is the amount that will be charged for the extension. To see the outcome, poll GET /api/v1/numbers/: on success expiration_time of the order moves forward by the chosen period. If the provider refuses the extension (for example, a week-long rental can't be extended right after purchase), nothing is charged and expiration_time stays the same.

Error Responses

Period Not in the Extension Table (400)

{
"period": [
"Period MONTH can't be used to extend a virtual_rent rental. Allowed: HOUR_4, HOUR_12, DAY, DAY_3, WEEK."
]
}

Number Can't Be Extended (400)

{
"detail": "You can only extend an active rental."
}

Insufficient Balance (402)

{
"detail": "You can top up your account balance."
}

Re-request an SMS (Replay)

Requests a new SMS for an existing order. The balance is charged price_usd of the order on each replay.

Endpoint

PUT /api/v1/numbers/{id}/replay/

Conditions

  • can_replay is true on the order
  • Account balance is at least the order's price_usd
  • For virtual and virtual_rent: the order has no active expiration time and its status is success

Request

curl -X 'PUT' \
'https://app.cyberyozh.com/api/v1/numbers/bb157566-8003-49f3-9e74-c1488acb9625/replay/' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Success Response (200)

{
"detail": "Replay processed"
}

The new SMS code arrives in history_sms_code of the order.

Error Responses

Insufficient Balance (402)

{
"detail": "You can top up your account balance."
}

Replay Not Allowed (404)

{
"detail": "The number can't be replayed."
}

Get Number Messages

Returns the full SMS history of an order with sender and text, newest first. Works for active and finished orders. GET /numbers/ returns only the latest codes, so use this endpoint for long rentals.

Endpoint

GET /api/v1/numbers/{id}/messages/

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoPage number, default 1
page_sizeintegerNoMessages per page, default 10, maximum 50

Request

curl -X 'GET' \
'https://app.cyberyozh.com/api/v1/numbers/bb157566-8003-49f3-9e74-c1488acb9625/messages/?page=1&page_size=10' \
-H 'accept: application/json' \
-H 'X-Api-Key: your_api_key_here'

Success Response (200)

{
"count": 1,
"next": null,
"previous": null,
"currentPage": 1,
"nextPage": null,
"prevPage": null,
"results": [
{
"id": "3f2b7c1e9a4d4e0f8b6a5c2d1e0f9a8b",
"sms_code": "123456",
"sender": "Telegram",
"text": "Telegram code: 123456",
"received_at": "2026-09-16T10:30:00Z",
"created_at": "2026-09-16T10:30:02Z"
}
]
}

Response Fields

FieldTypeDescription
idstringMessage ID
sms_codestringExtracted code
senderstring|nullSender as reported by the provider
textstring|nullFull SMS text; null for legacy messages
received_atstring|nullWhen the provider received the message (UTC)
created_atstringWhen the message was stored (UTC)

Error Responses

Order Not Found (404)

Returned when the order doesn't exist or belongs to another user.

Usage Example

import requests
import time

headers = {
'accept': 'application/json',
'X-Api-Key': 'your_api_key_here'
}

# Buy a number
order_response = requests.post(
'https://app.cyberyozh.com/api/v1/numbers/',
headers=headers,
json={
'provider': 'residential',
'period': 'MIN_15',
'service_code': 'tg',
'country_code': '667',
'need_fraud_score': True
}
)

order = order_response.json()
order_id = order['id']
print(f"Ordered number with ID: {order_id}")

# Poll for SMS codes
for _ in range(30): # Check for 5 minutes
details = requests.get(
f'https://app.cyberyozh.com/api/v1/numbers/{order_id}/',
headers=headers
).json()

if details['history_sms_code']:
print(f"Received SMS code: {details['history_sms_code'][0]}")
break

time.sleep(10)
else:
print("No SMS received, canceling...")
requests.put(
f'https://app.cyberyozh.com/api/v1/numbers/{order_id}/cancel/',
headers=headers
)