API docs · v1

OTP number rental API

Answers are JSON, errors follow problem+json. Every request needs the API token from your account page.

Last updated: 28 September 2026OpenAPI spec (JSON)
Your token · send it with every request
Sign in to see your API token
Sign in

Quick start

  1. Get the API token from your account page. The account needs API access turned on.
  2. Call GET /v1/services to get service ids and prices.
  3. Call POST /v1/rentals with the serviceId to rent a number, and keep the id.
  4. Call GET /v1/rentals/{id} every 5 seconds until status is no longer 0. status 1 means the code is in the code field; status 2 means 4–7 minutes passed without a code and the money was refunded.
curl -X POST "https://api.otpvn.com/v1/rentals" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"serviceId":1}'

curl "https://api.otpvn.com/v1/rentals/1234122" -H "Authorization: Bearer YOUR_API_TOKEN"

Conventions

Base URL
https://api.otpvn.com
Method
Read with GET; rent with POST and a JSON request body.
Authentication
Send the Authorization: Bearer <token> header with every request, using the 32-character token from your account page. Never put the token in the URL.
Responses
Success answers HTTP 200 (201 when renting) with the JSON data in the body. Errors answer HTTP 4xx or 5xx as application/problem+json: branch on code, the reason is in detail.
Language
Add ?lang=en or ?lang=zh to the URL, or send the X-Lang: en header, to get the error detail in English or Chinese. Vietnamese is the default; code and the data stay the same.
Phone number
phoneLocal has no leading 0 or country code (e.g. 987654321); type it into the app. phone is the full number, used when renting again.
Money
Prices and balances are integers in VND.
Time
createdAt is ISO 8601 with the Vietnam offset (+07:00).
Limits
Each account may send up to 100 requests per second and rent up to 15 times in a row, each less than 3 seconds after the previous one; beyond that it gets 429 too_many_requests. Each account can only keep a limited number of rentals waiting for a code at the same time; beyond that it gets 429 waiting_limit.
Freshness
A rental waiting for its code is refreshed every second, the balance within 2 seconds, the service list within 30 seconds; calling more often does not return newer data.
Zalo
Zalo cannot be rented through the API for now.

Endpoints

1

Get account balance

The account's current balance.

GEThttps://api.otpvn.com/v1/balance
Returned fields
balanceinteger
Current balance, in VND
Possible errors (HTTP · code)
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
Example response (HTTP 200)
{
  "balance": 186500
}
2

List carriers

Carrier names for the carriers field when renting. Vietnam: MOBIFONE, VINAPHONE, VIETTEL, VIETNAMOBILE, ITELECOM, WINTEL, GTEL. Laos: UNITEL, ETL, BEELINE, LAOTEL. The list also has carriers of other markets that are not used yet.

GEThttps://api.otpvn.com/v1/carriers
Each item of the returned array
idinteger
Carrier id
namestring
Carrier name, used in the carriers field
Possible errors (HTTP · code)
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
Example response (HTTP 200)
[
  {
    "id": 1,
    "name": "MOBIFONE"
  },
  {
    "id": 2,
    "name": "VINAPHONE"
  },
  {
    "id": 3,
    "name": "VIETTEL"
  },
  {
    "id": 4,
    "name": "VIETNAMOBILE"
  },
  {
    "id": 5,
    "name": "ITELECOM"
  },
  {
    "id": 6,
    "name": "VODAFONE_RO"
  },
  {
    "id": 7,
    "name": "WINTEL"
  },
  {
    "id": 8,
    "name": "METFONE"
  },
  {
    "id": 9,
    "name": "UNITEL"
  },
  {
    "id": 10,
    "name": "ETL"
  },
  {
    "id": 11,
    "name": "BEELINE"
  },
  {
    "id": 12,
    "name": "LAOTEL"
  },
  {
    "id": 13,
    "name": "GTEL"
  }
]
3

List services

Id, name and price of the services open to the API. Prices can change, so fetch the list again from time to time.

GEThttps://api.otpvn.com/v1/services?country=vn
Parameters
countryquery · string
vn: Vietnam (default) · la: Laos
Each item of the returned array
idinteger
Service id, used as serviceId
namestring
Service name
priceinteger
Price per rental, in VND
Possible errors (HTTP · code)
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
Example response (HTTP 200)
[
  {
    "id": 7,
    "name": "Facebook",
    "price": 800
  },
  {
    "id": 1,
    "name": "Momo",
    "price": 350
  }
]
4

Rent

Rents a new number for the service. The price is charged right away and refunded automatically if no code arrives within 4–7 minutes.

POSThttps://api.otpvn.com/v1/rentals
Parameters
serviceIdbody · integer · required
Service id, from the service list
countrybody · string
la to rent a Lao SIM · omit to rent a Vietnamese SIM
carriersbody · array
Carriers you want. Leave it out to take any carrier of that country.
includePrefixesbody · array
Prefixes you want, with the leading 0 (e.g. 096). Leave it out to take any prefix.
excludePrefixesbody · array
Prefixes you don't want, with the leading 0 (e.g. 097).
Returned fields
idinteger
Rental id, used to get the OTP
phonestring
Full number as stored, used for the phone field when renting again
phoneLocalstring
The number to enter in the app, without the leading 0 or country code
countryIsostring
Country code: VN or LA
countryCodestring
International dialling code: 84 or 856
balanceinteger
Balance left after the charge, in VND
Possible errors (HTTP · code)
400 · invalid_body
The request body is not valid JSON or a required field is missing
400 · invalid_carrier
The carrier does not belong to the chosen country
400 · invalid_prefix
The prefix does not belong to the chosen carriers
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
422 · api_not_supported
The service is not open to the API
422 · insufficient_balance
Insufficient balance
422 · out_of_stock
No matching number available, try again later
422 · service_closed
The service is temporarily closed
429 · waiting_limit
Too many rentals waiting for a code at once; detail gives the limit
503 · maintenance
Short system maintenance, try again in a few minutes
503 · busy
System busy, try again later
Example request body
{
  "serviceId": 1,
  "carriers": [
    "VINAPHONE",
    "VIETTEL"
  ],
  "includePrefixes": [
    "096",
    "097",
    "098"
  ]
}
Example response (HTTP 201)
{
  "id": 1234122,
  "phone": "0987654321",
  "phoneLocal": "987654321",
  "countryIso": "VN",
  "countryCode": "84",
  "balance": 185300
}
5

Rent a number again

Rent the same number again for the same service, e.g. when an app asks to verify again. Only within about 15–30 minutes of the previous rental, and while the SIM is still on the system.

POSThttps://api.otpvn.com/v1/rentals/rerent
Parameters
serviceIdbody · integer · required
Service id, from the service list
phonebody · string · required
The phone field of the previous rental
Returned fields
idinteger
Rental id, used to get the OTP
phonestring
Full number as stored, used for the phone field when renting again
phoneLocalstring
The number to enter in the app, without the leading 0 or country code
countryIsostring
Country code: VN or LA
countryCodestring
International dialling code: 84 or 856
balanceinteger
Balance left after the charge, in VND
Possible errors (HTTP · code)
400 · invalid_body
The request body is not valid JSON or a required field is missing
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
422 · api_not_supported
The service is not open to the API
422 · insufficient_balance
Insufficient balance
422 · service_closed
The service is temporarily closed
422 · service_unavailable
The service cannot be rented again yet, contact support
422 · rerent_unavailable
The number to rent again is not available right now
422 · rerent_forbidden
Cannot rent again: more than 15–30 minutes have passed since the previous rental, or the SIM is no longer on the system
422 · rerent_taken
Someone else is renting this number
422 · out_of_stock
No matching number available, try again later
429 · waiting_limit
Too many rentals waiting for a code at once; detail gives the limit
503 · maintenance
Short system maintenance, try again in a few minutes
503 · busy
System busy, try again later
Example request body
{
  "serviceId": 1,
  "phone": "0987654321"
}
Example response (HTTP 201)
{
  "id": 1234190,
  "phone": "0987654321",
  "phoneLocal": "987654321",
  "countryIso": "VN",
  "countryCode": "84",
  "balance": 184700
}
6

Get the OTP of a rental

Status and OTP of a rental. Call it every 5 seconds until status is no longer 0.

GEThttps://api.otpvn.com/v1/rentals/1234122
Parameters
idpath · integer · required
id returned when renting
Returned fields
idinteger
Rental id
serviceIdinteger
Service id
serviceNamestring
Service name
priceinteger
Price per rental, in VND
statusinteger
0: waiting for SMS · 1: completed · 2: expired, refunded
contentstring
Message text. For voice-call codes, a link to the recording. Absent until a message arrives
codestring
The extracted OTP code. Absent until a code arrives
isAudioboolean
true if the code came by phone call
phonestring
Full number as stored, used for the phone field when renting again
phoneLocalstring
The number to enter in the app, without the leading 0 or country code
countryIsostring
Country code: VN or LA
countryCodestring
International dialling code: 84 or 856
createdAtstring
Rental time, ISO 8601 with the Vietnam offset (+07:00)
Possible errors (HTTP · code)
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
404 · rental_not_found
The account has no such rental
Example response (HTTP 200)
{
  "id": 1234122,
  "serviceId": 1,
  "serviceName": "Momo",
  "price": 600,
  "status": 1,
  "content": "486460 la ma xac thuc Momo cua ban",
  "code": "486460",
  "isAudio": false,
  "phone": "0987654321",
  "phoneLocal": "987654321",
  "countryIso": "VN",
  "countryCode": "84",
  "createdAt": "2026-09-27T10:15:24.88+07:00"
}
7

Rental history

Rentals filtered by service, status and date range, newest first. All 5 parameters are required.

GEThttps://api.otpvn.com/v1/rentals?serviceId=1&status=1&limit=100&from=2026-09-01&to=2026-09-27
Parameters
serviceIdquery · integer · required
Service id
statusquery · integer · required
0: waiting for SMS · 1: completed · 2: expired
limitquery · integer · required
Maximum number of records
fromquery · string · required
Start date, yyyy-MM-dd
toquery · string · required
End date, yyyy-MM-dd
Each item of the returned array
idinteger
Rental id
serviceIdinteger
Service id
serviceNamestring
Service name
priceinteger
Price per rental, in VND
statusinteger
0: waiting for SMS · 1: completed · 2: expired, refunded
contentstring
Message text. For voice-call codes, a link to the recording. Absent until a message arrives
codestring
The extracted OTP code. Absent until a code arrives
isAudioboolean
true if the code came by phone call
phonestring
Full number as stored, used for the phone field when renting again
phoneLocalstring
The number to enter in the app, without the leading 0 or country code
countryIsostring
Country code: VN or LA
countryCodestring
International dialling code: 84 or 856
createdAtstring
Rental time, ISO 8601 with the Vietnam offset (+07:00)
Possible errors (HTTP · code)
400 · invalid_query
A query parameter is wrong or missing
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
Example response (HTTP 200)
[
  {
    "id": 1234101,
    "serviceId": 1,
    "serviceName": "Momo",
    "price": 600,
    "status": 1,
    "content": "https://audio.otpvn.com/20260927101215_7f3c2a.wav",
    "code": "731905",
    "isAudio": true,
    "phone": "0987654321",
    "phoneLocal": "987654321",
    "countryIso": "VN",
    "countryCode": "84",
    "createdAt": "2026-09-27T10:12:03.51+07:00"
  }
]

Error codes

400 · invalid_body
The request body is not valid JSON or a required field is missing
400 · invalid_query
A query parameter is wrong or missing
400 · invalid_carrier
The carrier does not belong to the chosen country
400 · invalid_prefix
The prefix does not belong to the chosen carriers
401 · invalid_token
The token is missing, wrong or no longer valid
401 · api_disabled
The account has no API access
404 · rental_not_found
The account has no such rental
422 · api_not_supported
The service is not open to the API
422 · insufficient_balance
Insufficient balance
422 · out_of_stock
No matching number available, try again later
422 · service_closed
The service is temporarily closed
422 · service_unavailable
The service cannot be rented again yet, contact support
422 · rerent_unavailable
The number to rent again is not available right now
422 · rerent_forbidden
Cannot rent again: more than 15–30 minutes have passed since the previous rental, or the SIM is no longer on the system
422 · rerent_taken
Someone else is renting this number
429 · waiting_limit
Too many rentals waiting for a code at once; detail gives the limit
429 · too_many_requests
Too fast: over the requests per second of the account, or too many rentals in a row; wait for Retry-After and try again
503 · maintenance
Short system maintenance, try again in a few minutes
503 · busy
System busy, try again later
500 · internal
System error, try again later
Rental status (status)
0
Waiting for SMS
1
Completed
2
Expired, money refunded
Example error
{
  "type": "https://otpvn.com/errors/insufficient_balance",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "insufficient_balance",
  "detail": "Số dư quý khách không đủ !"
}