Catalogue
https://numestri.com/api/v1 /catalog The catalogue is a tree, one level per call, each scoped to the choice above it: platforms → countries → providers → options. Every id along the way is what /purchase/sms takes.
Ordering from it:
service+country: the best option in stock, failing over to the next if it cannot deliver.service+country+provider: that provider only, its best option first.service+country+option: exactly that option at its listed price, or nothing (never a substitute).
Every level returns an ETag; send it back as If-None-Match for a bodiless 304 while nothing changed.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
If-None-MatchstringheaderETag from your previous fetch of this level, a comma-separated list of them, or *. Compared weakly (W/"x" matches "x"). A match answers 304 with no body.cURL
curl -X GET "https://numestri.com/api/v1/catalog" \
-H "If-None-Match: <value>"TypeScript
const res = await fetch('https://numestri.com/api/v1/catalog', {
method: 'GET',
headers: {
'If-None-Match': '<value>',
},
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/catalog",
headers={
"If-None-Match": "<value>",
},
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/catalog", nil)
req.Header.Set("If-None-Match", "<value>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/catalog');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['If-None-Match: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/catalog')
req = Net::HTTP::Get.new(uri)
req['If-None-Match'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/catalog"))
.header("If-None-Match", "<value>")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"prices_at": "2026-10-14T01:40:00.000Z",
"platforms_in_stock": 1326,
"tree": [
{
"level": 1,
"list": "platforms",
"path": "/api/v1/catalog/platforms"
},
{
"level": 2,
"list": "countries for a platform",
"path": "/api/v1/catalog/platforms/{platform}/countries"
},
{
"level": 3,
"list": "providers for a platform in a country",
"path": "/api/v1/catalog/platforms/{platform}/countries/{country}/providers"
},
{
"level": 4,
"list": "a provider's options",
"path": "/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options"
}
],
"ordering": {
"endpoint": "/api/v1/purchase/sms",
"choose_by": [
"service + country: the best option, failing over to the next",
"service + country + provider: that provider only, its best option first",
"service + country + option: exactly that option at its listed price, or nothing"
]
}
}Esquema
successobligatorioprices_atstringobligatorioplatforms_in_stockintegertreeobject[]Mostrar parámetros secundarios
levelintegerliststringpathstringorderingobjectMostrar parámetros secundarios
endpointstringchoose_bystring[]If-None-Match ETag still matches: nothing at this level changed. No body.param names it.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /catalog/platforms Every platform with numbers in stock now, sorted by name, with how many countries it is in stock in and its lowest price. id is the exact platform id every other endpoint takes.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
If-None-MatchstringheaderETag from your previous fetch of this level, a comma-separated list of them, or *. Compared weakly (W/"x" matches "x"). A match answers 304 with no body.cURL
curl -X GET "https://numestri.com/api/v1/catalog/platforms" \
-H "If-None-Match: <value>"TypeScript
const res = await fetch('https://numestri.com/api/v1/catalog/platforms', {
method: 'GET',
headers: {
'If-None-Match': '<value>',
},
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/catalog/platforms",
headers={
"If-None-Match": "<value>",
},
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/catalog/platforms", nil)
req.Header.Set("If-None-Match", "<value>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/catalog/platforms');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['If-None-Match: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/catalog/platforms')
req = Net::HTTP::Get.new(uri)
req['If-None-Match'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/catalog/platforms"))
.header("If-None-Match", "<value>")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"prices_at": "2026-10-14T01:40:00.000Z",
"count": 1326,
"next": "/api/v1/catalog/platforms/{platform}/countries",
"data": [
{
"id": "discord",
"name": "Discord",
"countries": 12,
"from_price": "0.07",
"from_price_cents": 7
}
]
}Esquema
successobligatorioprices_atstringobligatoriocountintegernextstringdataCatalogPlatform[]Mostrar parámetros secundarios
idstringobligatorio/purchase/sms takes as service.namestringobligatoriocountriesintegerobligatoriofrom_pricestringobligatoriofrom_price_centsintegerobligatorioIf-None-Match ETag still matches: nothing at this level changed. No body.param names it.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /catalog/platforms/{platform}/countries The countries one platform is in stock in, sorted by name, with how many providers sell it there and its lowest price.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
platformstringpathobligatorio/catalog/platforms lists it (e.g. whatsapp). Not a name: an id that has nothing in stock (or does not exist) is a 404.If-None-MatchstringheaderETag from your previous fetch of this level, a comma-separated list of them, or *. Compared weakly (W/"x" matches "x"). A match answers 304 with no body.cURL
curl -X GET "https://numestri.com/api/v1/catalog/platforms/{platform}/countries" \
-H "If-None-Match: <value>"TypeScript
const res = await fetch('https://numestri.com/api/v1/catalog/platforms/{platform}/countries', {
method: 'GET',
headers: {
'If-None-Match': '<value>',
},
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/catalog/platforms/{platform}/countries",
headers={
"If-None-Match": "<value>",
},
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/catalog/platforms/{platform}/countries", nil)
req.Header.Set("If-None-Match", "<value>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/catalog/platforms/{platform}/countries');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['If-None-Match: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/catalog/platforms/{platform}/countries')
req = Net::HTTP::Get.new(uri)
req['If-None-Match'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/catalog/platforms/{platform}/countries"))
.header("If-None-Match", "<value>")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"prices_at": "2026-10-14T01:40:00.000Z",
"platform": "discord",
"count": 12,
"next": "/api/v1/catalog/platforms/discord/countries/{country}/providers",
"data": [
{
"id": "US",
"name": "United States",
"providers": 2,
"from_price": "0.07",
"from_price_cents": 7
}
]
}Esquema
successobligatorioprices_atstringobligatorioplatformstringcountintegernextstringdataCatalogCountry[]Mostrar parámetros secundarios
idstringobligatorio/purchase/sms takes as country.namestringobligatorioprovidersintegerobligatoriofrom_pricestringobligatoriofrom_price_centsintegerobligatorioIf-None-Match ETag still matches: nothing at this level changed. No body.param names it.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringparam: platform).Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /catalog/platforms/{platform}/countries/{country}/providers The providers selling this platform in this country, best first, by anonymous id — never a supplier name. rank: 1 is the provider an order without provider or option tries first. Pass an id as provider to /purchase/sms to order only from it.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
platformstringpathobligatorio/catalog/platforms lists it (e.g. whatsapp). Not a name: an id that has nothing in stock (or does not exist) is a 404.countrystringpathobligatorio…/countries lists it (e.g. US, uppercase). Anything else is a 404.If-None-MatchstringheaderETag from your previous fetch of this level, a comma-separated list of them, or *. Compared weakly (W/"x" matches "x"). A match answers 304 with no body.cURL
curl -X GET "https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers" \
-H "If-None-Match: <value>"TypeScript
const res = await fetch('https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers', {
method: 'GET',
headers: {
'If-None-Match': '<value>',
},
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers",
headers={
"If-None-Match": "<value>",
},
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers", nil)
req.Header.Set("If-None-Match", "<value>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['If-None-Match: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers')
req = Net::HTTP::Get.new(uri)
req['If-None-Match'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers"))
.header("If-None-Match", "<value>")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"prices_at": "2026-10-14T01:40:00.000Z",
"platform": "discord",
"country": "US",
"count": 2,
"next": "/api/v1/catalog/platforms/discord/countries/US/providers/{provider}/options",
"data": [
{
"id": "prv_k3Jd9QmXa2",
"rank": 1,
"options": 2,
"from_price": "0.07",
"from_price_cents": 7,
"quality": null,
"success_rate": null
},
{
"id": "prv_Vb7nR2sYq0",
"rank": 2,
"options": 1,
"from_price": "0.12",
"from_price_cents": 12,
"quality": "good",
"success_rate": 90
}
]
}Esquema
successobligatorioprices_atstringobligatorioplatformstringcountrystringcountintegernextstringdataCatalogProvider[]Mostrar parámetros secundarios
idstringobligatoriorankintegerobligatorioprovider or option tries first.optionsintegerobligatoriofrom_pricestringobligatoriofrom_price_centsintegerobligatorioqualitystringobligatorionull until there are enough orders to rate.success_rateintegerobligatorionull with fewer than 5 orders.If-None-Match ETag still matches: nothing at this level changed. No body.param names it.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringparam: country).Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /catalog/platforms/{platform}/countries/{country}/providers/{provider}/options One provider's options for this platform in this country — one per pool or product it sells from — best first. Pass an option to /purchase/sms to buy exactly that offer at that price; if it has since disappeared the order fails with OPTION_GONE rather than buying something else.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
platformstringpathobligatorio/catalog/platforms lists it (e.g. whatsapp). Not a name: an id that has nothing in stock (or does not exist) is a 404.countrystringpathobligatorio…/countries lists it (e.g. US, uppercase). Anything else is a 404.providerstringpathobligatorio…/providers lists it.If-None-MatchstringheaderETag from your previous fetch of this level, a comma-separated list of them, or *. Compared weakly (W/"x" matches "x"). A match answers 304 with no body.cURL
curl -X GET "https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options" \
-H "If-None-Match: <value>"TypeScript
const res = await fetch('https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options', {
method: 'GET',
headers: {
'If-None-Match': '<value>',
},
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options",
headers={
"If-None-Match": "<value>",
},
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options", nil)
req.Header.Set("If-None-Match", "<value>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['If-None-Match: <value>']);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options')
req = Net::HTTP::Get.new(uri)
req['If-None-Match'] = '<value>'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options"))
.header("If-None-Match", "<value>")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"prices_at": "2026-10-14T01:40:00.000Z",
"platform": "discord",
"country": "US",
"provider": "prv_k3Jd9QmXa2",
"count": 2,
"order": {
"endpoint": "/api/v1/purchase/sms",
"params": {
"service": "discord",
"country": "US",
"option": "{option}"
}
},
"data": [
{
"option": "k3Jd9QmXa2Lp0cWe",
"rank": 1,
"price": "0.07",
"price_cents": 7,
"quality": null,
"success_rate": null,
"stock": "plenty"
},
{
"option": "Vb7nR2sYq0Te4hUa",
"rank": 2,
"price": "0.10",
"price_cents": 10,
"quality": null,
"success_rate": null,
"stock": "limited"
}
]
}Esquema
successobligatorioprices_atstringobligatorioplatformstringcountrystringproviderstringcountintegerorderobjectMostrar parámetros secundarios
endpointstringparamsobjectdataOption[]Mostrar parámetros secundarios
optionstringobligatoriooption to buy exactly this offer at this price.rankintegerobligatoriopricestringobligatorioprice_centsintegerobligatorioqualitystringobligatorionull until there are enough orders to rate.success_rateintegerobligatorionull with fewer than 5 orders.stockstringobligatorioIf-None-Match ETag still matches: nothing at this level changed. No body.param names it.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringparam: provider).Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /request/price What /purchase/sms would charge right now for a platform and country, the option it would use first, and every option behind it (best first). price is the best option in stock; high_price the most expensive one in stock.
No API key needed. Without one you get public list prices, rate-limited per IP address. Send your key to get the prices for your account (which can differ from the public list) and the per-account limit; an invalid key is still refused with 403.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
servicestringqueryobligatorio/catalog/platforms lists it (e.g. whatsapp). Names and aliases such as WhatsApp are rejected with 400.countrystringqueryobligatorio/catalog/platforms/{platform}/countries lists it (e.g. US). Country names and lowercase codes are rejected with 400.cURL
curl -X GET "https://numestri.com/api/v1/request/price?service=&country="TypeScript
const res = await fetch('https://numestri.com/api/v1/request/price?service=&country=', {
method: 'GET',
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/request/price?service=&country=",
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/request/price?service=&country=", nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/request/price?service=&country=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/request/price?service=&country=')
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/request/price?service=&country="))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
{
"success": 1,
"service": {
"id": "whatsapp",
"name": "WhatsApp"
},
"country": {
"id": "US",
"name": "United States"
},
"price": "0.26",
"price_cents": 26,
"high_price": "0.39",
"success_rate": 90,
"quality": "good",
"option": "k3Jd9QmXa2Lp0cWe",
"options": [
{
"option": "k3Jd9QmXa2Lp0cWe",
"provider": "prv_k3Jd9QmXa2",
"rank": 1,
"price": "0.26",
"price_cents": 26,
"quality": "good",
"success_rate": 90,
"stock": "plenty",
"in_stock": true
},
{
"option": "Vb7nR2sYq0Te4hUa",
"provider": "prv_Vb7nR2sYq0",
"rank": 2,
"price": "0.39",
"price_cents": 39,
"quality": null,
"success_rate": null,
"stock": "limited",
"in_stock": true
}
],
"shared_inbox": null
}Esquema
successobligatorioserviceobjectobligatorioMostrar parámetros secundarios
idstringobligatorionamestringobligatoriocountryobjectobligatorioMostrar parámetros secundarios
idstringobligatorionamestringobligatoriopricestringobligatoriooption is charged.price_centsintegerobligatoriohigh_pricestringobligatoriosuccess_rateintegerobligatorionull with fewer than 5 orders.qualitystringobligatorionull until there are enough orders to rate.optionstringobligatoriooption tries first.optionsPriceOption[]obligatorioMostrar parámetros secundarios
optionstringobligatoriooption to buy exactly this offer at this price.rankintegerobligatoriopricestringobligatorioprice_centsintegerobligatorioqualitystringobligatorionull until there are enough orders to rate.success_rateintegerobligatorionull with fewer than 5 orders.stockstringobligatorioproviderstringobligatorioin_stockbooleanobligatorioreadinessobjectobligatorioactivating until it is ready, and a code requested from the platform before then is lost.Mostrar parámetros secundarios
readystringobligatorioinstant: usually ready at purchase. activates: usually needs ready_in_seconds first. unknown: not enough orders yet.ready_in_secondsintegerobligatorioready_in_seconds_p90integerobligatoriofirst_code_secondsintegerobligatoriofirst_code_seconds_p90integerobligatoriobasisstringobligatoriomeasured on recent orders, or seeded: our estimate until enough orders exist. Null when ready is unknown.shared_inboxobjectobligatorionumber_class=shared), when one is available; otherwise null.Mostrar parámetros secundarios
pricestringprice_centsintegerservice/country is not an exact id (param names which).Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringtype: OUT_OF_STOCK).Ejemplo
{
"success": 0,
"message": "No WhatsApp numbers in United States right now.",
"type": "OUT_OF_STOCK",
"options": [],
"shared_inbox": null
}Esquema
successobligatoriomessagestringobligatoriotypeobligatoriooptionsPriceOption[]obligatorioMostrar parámetros secundarios
optionstringobligatoriooption to buy exactly this offer at this price.rankintegerobligatoriopricestringobligatorioprice_centsintegerobligatorioqualitystringobligatorionull until there are enough orders to rate.success_rateintegerobligatorionull with fewer than 5 orders.stockstringobligatorioproviderstringobligatorioin_stockbooleanobligatorioreadinessobjectobligatorioactivating until it is ready, and a code requested from the platform before then is lost.Mostrar parámetros secundarios
readystringobligatorioinstant: usually ready at purchase. activates: usually needs ready_in_seconds first. unknown: not enough orders yet.ready_in_secondsintegerobligatorioready_in_seconds_p90integerobligatoriofirst_code_secondsintegerobligatoriofirst_code_seconds_p90integerobligatoriobasisstringobligatoriomeasured on recent orders, or seeded: our estimate until enough orders exist. Null when ready is unknown.shared_inboxobjectobligatorionumber_class=shared), when one is available; otherwise null.Mostrar parámetros secundarios
pricestringprice_centsintegerRetry-After seconds.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Error
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstring{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Failure
successobligatoriomessagestringobligatoriotypestringOUT_OF_STOCK, BALANCE_ERROR, PRICE_NOT_FOUND and SERVICE_UNAVAILABLE, with the exact reason in code; see OrderFailure.{
"success": 0,
"message": "Insufficient balance.",
"type": "BALANCE_ERROR"
}https://numestri.com/api/v1 /service/retrieve_all Every platform with something to buy, sorted by name, in the ID/name shape most verification APIs use. No API key needed. ID is what /purchase/sms takes as service. /catalog/platforms has the same list with country counts.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
Parámetros
countrystringquerycURL
curl -X GET "https://numestri.com/api/v1/service/retrieve_all?country="TypeScript
const res = await fetch('https://numestri.com/api/v1/service/retrieve_all?country=', {
method: 'GET',
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/service/retrieve_all?country=",
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/service/retrieve_all?country=", nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/service/retrieve_all?country=');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/service/retrieve_all?country=')
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/service/retrieve_all?country="))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
[
{
"ID": "telegram",
"name": "Telegram",
"from_price": "0.26"
}
]Esquema
IDstringobligatorio/purchase/sms takes as service.namestringobligatoriofrom_pricestringobligatoriocountry is set.country (param: country). Never cached.Ejemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringhttps://numestri.com/api/v1 /country/retrieve_all Every country numbers are sold in, sorted by name, in the ID/name/short_name shape most verification APIs use. No API key needed. ID is the ISO code /purchase/sms takes as country.
Also accepts POST, with the same parameters in a form (application/x-www-form-urlencoded) or JSON body.
cURL
curl -X GET "https://numestri.com/api/v1/country/retrieve_all"TypeScript
const res = await fetch('https://numestri.com/api/v1/country/retrieve_all', {
method: 'GET',
});
const data = await res.json();Python
import requests
res = requests.request(
"GET",
"https://numestri.com/api/v1/country/retrieve_all",
)
data = res.json()Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://numestri.com/api/v1/country/retrieve_all", nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}PHP
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://numestri.com/api/v1/country/retrieve_all');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Ruby
require 'net/http'
require 'uri'
uri = URI('https://numestri.com/api/v1/country/retrieve_all')
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
puts res.bodyJava
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://numestri.com/api/v1/country/retrieve_all"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Respuestas
Ejemplo
[
{
"ID": "US",
"name": "United States",
"short_name": "US"
}
]Esquema
IDstringobligatorio/purchase/sms takes as country.namestringobligatorioshort_namestringobligatorioEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstringEjemplo
{
"success": 0,
"errors": [
{
"message": "You are missing a required parameter for this request.",
"param": "country",
"description": "Country code from /api/v1/catalog/platforms/{platform}/countries, e.g. US"
}
]
}Esquema
successobligatorioerrorsobject[]obligatorioMostrar parámetros secundarios
messagestringobligatorioparamstringdescriptionstring