Catalogue

Embed
Preview of the card
<a href="https://numestri.com/docs/ref-catalogue"><img src="https://numestri.com/docs/_api/public/orgs/25229885-9620-4c08-bd2e-a0d0d74ac8b6/spaces/ef21e0c3-966d-4b03-b6d2-e66d449835d4/pages/d647e64b-3370-4b55-a9fe-5350811d183f/social-card.svg?v=3e7ae33eec8b" alt="Catalogue" width="600" height="315"></a>
GEThttps://numestri.com/api/v1/catalog
How the catalogue tree is walked

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.

Parameters
If-None-Matchstringheader
The ETag 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.
Code samples
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.body
Java
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());
Responses
200 This level of the tree.
Example
{
  "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"
    ]
  }
}
Schema
successrequired
prices_atstringrequired
When the prices behind this level were read.
platforms_in_stockinteger
treeobject[]
Show child parameters
levelinteger
liststring
pathstring
orderingobject
Show child parameters
endpointstring
choose_bystring[]
304 The If-None-Match ETag still matches: nothing at this level changed. No body.
400 A parameter (or the API key) is missing or invalid. param names it.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/catalog/platforms
Level 1: platforms in stock

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.

Parameters
If-None-Matchstringheader
The ETag 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.
Code samples
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.body
Java
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());
Responses
200 This level of the tree.
Example
{
  "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
    }
  ]
}
Schema
successrequired
prices_atstringrequired
When the prices behind this level were read.
countinteger
nextstring
dataCatalogPlatform[]
Sorted by name.
Show child parameters
idstringrequired
Platform id: what /purchase/sms takes as service.
namestringrequired
countriesintegerrequired
Countries it is in stock in.
from_pricestringrequired
Lowest price anywhere, in dollars.
from_price_centsintegerrequired
The same amount in integer US cents.
304 The If-None-Match ETag still matches: nothing at this level changed. No body.
400 A parameter (or the API key) is missing or invalid. param names it.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/catalog/platforms/{platform}/countries
Level 2: countries for a platform

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.

Parameters
platformstringpathrequired
Platform id exactly as /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-Matchstringheader
The ETag 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.
Code samples
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.body
Java
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());
Responses
200 This level of the tree.
Example
{
  "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
    }
  ]
}
Schema
successrequired
prices_atstringrequired
When the prices behind this level were read.
platformstring
countinteger
nextstring
dataCatalogCountry[]
Sorted by country name.
Show child parameters
idstringrequired
ISO code: what /purchase/sms takes as country.
namestringrequired
providersintegerrequired
Providers with this platform in stock here.
from_pricestringrequired
US dollars, as a fixed two-decimal string.
from_price_centsintegerrequired
The same amount in integer US cents.
304 The If-None-Match ETag still matches: nothing at this level changed. No body.
400 A parameter (or the API key) is missing or invalid. param names it.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
404 Nothing is in stock for that platform id (param: platform).
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers
Level 3: providers for a platform in a country

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.

Parameters
platformstringpathrequired
Platform id exactly as /catalog/platforms lists it (e.g. whatsapp). Not a name: an id that has nothing in stock (or does not exist) is a 404.
countrystringpathrequired
ISO 3166-1 alpha-2 code exactly as …/countries lists it (e.g. US, uppercase). Anything else is a 404.
If-None-Matchstringheader
The ETag 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.
Code samples
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.body
Java
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());
Responses
200 This level of the tree.
Example
{
  "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
    }
  ]
}
Schema
successrequired
prices_atstringrequired
When the prices behind this level were read.
platformstring
countrystring
countinteger
nextstring
dataCatalogProvider[]
Best first.
Show child parameters
idstringrequired
Anonymous, stable provider id. Never a supplier name.
rankintegerrequired
1 = the provider an order without provider or option tries first.
optionsintegerrequired
Options this provider has in stock here.
from_pricestringrequired
US dollars, as a fixed two-decimal string.
from_price_centsintegerrequired
The same amount in integer US cents.
qualitystringrequired
Quality band from real orders on this exact platform and country. null until there are enough orders to rate.
excellent | good | fair | poor
success_rateintegerrequired
Observed success rate in percent, rounded to the nearest 5. null with fewer than 5 orders.
304 The If-None-Match ETag still matches: nothing at this level changed. No body.
400 A parameter (or the API key) is missing or invalid. param names it.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
404 Nothing is in stock for that platform in that country (param: country).
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/catalog/platforms/{platform}/countries/{country}/providers/{provider}/options
Level 4: a provider's 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.

Parameters
platformstringpathrequired
Platform id exactly as /catalog/platforms lists it (e.g. whatsapp). Not a name: an id that has nothing in stock (or does not exist) is a 404.
countrystringpathrequired
ISO 3166-1 alpha-2 code exactly as …/countries lists it (e.g. US, uppercase). Anything else is a 404.
providerstringpathrequired
Anonymous provider id exactly as …/providers lists it.
If-None-Matchstringheader
The ETag 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.
Code samples
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.body
Java
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());
Responses
200 This level of the tree.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
prices_atstringrequired
When the prices behind this level were read.
platformstring
countrystring
providerstring
countinteger
orderobject
How to buy one of these.
Show child parameters
endpointstring
paramsobject
dataOption[]
Best first.
Show child parameters
optionstringrequired
Opaque option id. Pass it as option to buy exactly this offer at this price.
rankintegerrequired
Position within the list, best first.
pricestringrequired
US dollars, as a fixed two-decimal string.
price_centsintegerrequired
The same amount in integer US cents.
qualitystringrequired
Quality band from real orders on this exact platform and country. null until there are enough orders to rate.
excellent | good | fair | poor
success_rateintegerrequired
Observed success rate in percent, rounded to the nearest 5. null with fewer than 5 orders.
stockstringrequired
Coarse stock band; exact counts are not exposed.
plenty | limited | none | unknown
304 The If-None-Match ETag still matches: nothing at this level changed. No body.
400 A parameter (or the API key) is missing or invalid. param names it.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
404 That provider has nothing in stock for this platform and country (param: provider).
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/request/price
Price a platform in a country

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.

Parameters
servicestringqueryrequired
Platform id, exactly as /catalog/platforms lists it (e.g. whatsapp). Names and aliases such as WhatsApp are rejected with 400.
countrystringqueryrequired
ISO 3166-1 alpha-2 country code, exactly as /catalog/platforms/{platform}/countries lists it (e.g. US). Country names and lowercase codes are rejected with 400.
Code samples
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.body
Java
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());
Responses
200 The current price and options.
Example
{
  "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
}
Schema
successrequired
serviceobjectrequired
Show child parameters
idstringrequired
namestringrequired
countryobjectrequired
Show child parameters
idstringrequired
namestringrequired
pricestringrequired
Price of the best option in stock: what an order without option is charged.
price_centsintegerrequired
The same amount in integer US cents.
high_pricestringrequired
Price of the most expensive option in stock.
success_rateintegerrequired
Observed success rate in percent, rounded to the nearest 5. null with fewer than 5 orders.
qualitystringrequired
Quality band from real orders on this exact platform and country. null until there are enough orders to rate.
excellent | good | fair | poor
optionstringrequired
The best option in stock: the one an order without option tries first.
optionsPriceOption[]required
Every option, best first.
Show child parameters
optionstringrequired
Opaque option id. Pass it as option to buy exactly this offer at this price.
rankintegerrequired
Position within the list, best first.
pricestringrequired
US dollars, as a fixed two-decimal string.
price_centsintegerrequired
The same amount in integer US cents.
qualitystringrequired
Quality band from real orders on this exact platform and country. null until there are enough orders to rate.
excellent | good | fair | poor
success_rateintegerrequired
Observed success rate in percent, rounded to the nearest 5. null with fewer than 5 orders.
stockstringrequired
Coarse stock band; exact counts are not exposed.
plenty | limited | none | unknown
providerstringrequired
Anonymous, stable provider id. Never a supplier name.
in_stockbooleanrequired
readinessobjectrequired
How soon this option's numbers can receive, and how soon a first code usually lands, from recent orders (median and 90th percentile). Some numbers have to activate for a few minutes after purchase: an order for one reports activating until it is ready, and a code requested from the platform before then is lost.
Show child parameters
readystringrequired
instant: usually ready at purchase. activates: usually needs ready_in_seconds first. unknown: not enough orders yet.
instant | activates | unknown
ready_in_secondsintegerrequired
Typical (median) seconds from purchase to ready, when it activates.
ready_in_seconds_p90integerrequired
Nine in ten were ready within this many seconds.
first_code_secondsintegerrequired
Typical (median) seconds from purchase to the first code.
first_code_seconds_p90integerrequired
basisstringrequired
measured on recent orders, or seeded: our estimate until enough orders exist. Null when ready is unknown.
measured | seeded
shared_inboxobjectrequired
A cheaper public inbox anyone can read (number_class=shared), when one is available; otherwise null.
Show child parameters
pricestring
US dollars, as a fixed two-decimal string.
price_centsinteger
The same amount in integer US cents.
400 Missing parameter, or service/country is not an exact id (param names which).
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
403 The API key is not valid.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
409 Nothing is in stock for this pairing right now (type: OUT_OF_STOCK).
Example
{
  "success": 0,
  "message": "No WhatsApp numbers in United States right now.",
  "type": "OUT_OF_STOCK",
  "options": [],
  "shared_inbox": null
}
Schema
successrequired
messagestringrequired
typerequired
optionsPriceOption[]required
Show child parameters
optionstringrequired
Opaque option id. Pass it as option to buy exactly this offer at this price.
rankintegerrequired
Position within the list, best first.
pricestringrequired
US dollars, as a fixed two-decimal string.
price_centsintegerrequired
The same amount in integer US cents.
qualitystringrequired
Quality band from real orders on this exact platform and country. null until there are enough orders to rate.
excellent | good | fair | poor
success_rateintegerrequired
Observed success rate in percent, rounded to the nearest 5. null with fewer than 5 orders.
stockstringrequired
Coarse stock band; exact counts are not exposed.
plenty | limited | none | unknown
providerstringrequired
Anonymous, stable provider id. Never a supplier name.
in_stockbooleanrequired
readinessobjectrequired
How soon this option's numbers can receive, and how soon a first code usually lands, from recent orders (median and 90th percentile). Some numbers have to activate for a few minutes after purchase: an order for one reports activating until it is ready, and a code requested from the platform before then is lost.
Show child parameters
readystringrequired
instant: usually ready at purchase. activates: usually needs ready_in_seconds first. unknown: not enough orders yet.
instant | activates | unknown
ready_in_secondsintegerrequired
Typical (median) seconds from purchase to ready, when it activates.
ready_in_seconds_p90integerrequired
Nine in ten were ready within this many seconds.
first_code_secondsintegerrequired
Typical (median) seconds from purchase to the first code.
first_code_seconds_p90integerrequired
basisstringrequired
measured on recent orders, or seeded: our estimate until enough orders exist. Null when ready is unknown.
measured | seeded
shared_inboxobjectrequired
A cheaper public inbox anyone can read (number_class=shared), when one is available; otherwise null.
Show child parameters
pricestring
US dollars, as a fixed two-decimal string.
price_centsinteger
The same amount in integer US cents.
429 Over the rate limit (32 requests per second per account by default). Wait Retry-After seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Supply temporarily unreachable.
Example
{
  "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
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
{
  "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
successrequired
messagestringrequired
Human-readable, safe to show.
typestring
Machine-readable category. Ordering, rental and email endpoints use OUT_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"
}
GEThttps://numestri.com/api/v1/service/retrieve_all
List platforms (public)

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.

Parameters
countrystringquery
Only platforms sold in this ISO country code, with their price there.
Code samples
cURL
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.body
Java
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());
Responses
200 Every platform. Cached publicly for 120 seconds.
Example
[
  {
    "ID": "telegram",
    "name": "Telegram",
    "from_price": "0.26"
  }
]
Schema
IDstringrequired
Platform id: what /purchase/sms takes as service.
namestringrequired
from_pricestringrequired
Lowest price, in the given country when country is set.
400 Unknown country (param: country). Never cached.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
GEThttps://numestri.com/api/v1/country/retrieve_all
List countries (public)

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.

Code samples
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.body
Java
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());
Responses
200 Every country. Cached publicly for 300 seconds.
Example
[
  {
    "ID": "US",
    "name": "United States",
    "short_name": "US"
  }
]
Schema
IDstringrequired
ISO code: what /purchase/sms takes as country.
namestringrequired
short_namestringrequired
The same ISO code.
500 Something went wrong on our side.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
503 Prices are being refreshed after a restart. Retry in a few seconds.
Example
{
  "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"
    }
  ]
}
Schema
successrequired
errorsobject[]required
Show child parameters
messagestringrequired
paramstring
The parameter at fault, when there is one.
descriptionstring
What the parameter should contain.
Updated