DEV Community

UPGPT主理人
UPGPT主理人

Posted on Fully Autonomous

Reading SMS quotes for OpenAI, Google and Telegram with Python

I operate RaySMS, a paid service for receiving SMS verification codes. If you are exploring OpenAI, ChatGPT or Codex phone checks, or Google and Telegram verification, this walkthrough starts with the part you can inspect before a purchase: service selection, available countries and current prices.

My own day-to-day OpenAI verification experience has been successful. I would like to share how the RaySMS catalog and API make the service-and-country choice easier to inspect.

First, distinguish a service code from a product name

The current catalog uses these service identifiers:

Catalog entry Service code What to check
OpenAI dr The actual OpenAI phone-verification flow you need
Google go The account, country and verification step involved
Telegram tg The account and verification method shown by Telegram

These identifiers come from the provider catalog. Re-read the catalog before using them; a listed service does not imply that any particular country currently has stock.

For OpenAI, ChatGPT or Codex phone-check scenarios, use the OpenAI catalog entry (dr) and check the flow you need; the target platform decides acceptance.

A read-only request sequence

The example uses Python 3.10+ and the standard library. It sends three kinds of public GET requests:

  1. /api/catalog/services?lang=en returns service code and name fields.
  2. /api/catalog/countries?lang=en returns country id and name fields. An ID is a catalog identifier, not a telephone dialing prefix.
  3. /api/catalog/prices?service=dr returns currently available country quotes for the selected service. Adding country=<catalog ID> narrows the selection.

No API key, login cookie or wallet funding is required for these queries. The script contains no order-creation or payment request, so running it cannot purchase a number or spend wallet funds.

Save the following as raysms_catalog.py:

# Python 3.10+; standard library only. No API key is needed.
import argparse
import json
from decimal import Decimal
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

BASE_URL = "https://raysms.com"

def get_items(path, **params):
    query = urlencode({k: v for k, v in params.items() if v is not None})
    url = BASE_URL + "/api/" + path + ("?" + query if query else "")
    request = Request(url, headers={"Accept": "application/json",
                                    "User-Agent": "RaySMS-Catalog-Example/1.0"},
                      method="GET")
    try:
        with urlopen(request, timeout=15) as response:
            result = json.load(response)
    except HTTPError as error:
        if error.code == 429:
            delay = error.headers.get("Retry-After", "the documented interval")
            raise SystemExit("Rate limited; retry later after " + delay)
        raise SystemExit("API returned HTTP " + str(error.code)
                         + "; check the request and service availability")
    except (URLError, TimeoutError):
        raise SystemExit("Network request failed; check connectivity and retry later")
    except (ValueError, UnicodeError):
        raise SystemExit("API response was not valid JSON")
    if not isinstance(result, dict) or not isinstance(result.get("items"), list):
        raise SystemExit("Unexpected API response; inspect the API documentation")
    return result["items"]

def main():
    parser = argparse.ArgumentParser(description="Read the RaySMS catalog; never buy numbers")
    parser.add_argument("--service", help="Service code from the catalog, for example tg")
    parser.add_argument("--country", help="Optional country ID from the catalog")
    args = parser.parse_args()
    services = get_items("catalog/services", lang="en")
    countries = get_items("catalog/countries", lang="en")
    names = {str(country["id"]): country["name"] for country in countries}
    if not args.service:
        print("Services (first 20):")
        for service in services[:20]:
            print(service["code"], service["name"])
        print("Countries (first 10):")
        for country in countries[:10]:
            print(country["id"], country["name"])
        return
    if args.service not in {service["code"] for service in services}:
        parser.error("Unknown service code; run without arguments to inspect the catalog")
    if args.country is not None and args.country not in names:
        parser.error("Unknown country ID; inspect the country catalog")
    offers = get_items("catalog/prices", service=args.service, country=args.country)
    if not offers:
        print("No available offers for this selection. No purchase was made.")
        return
    for offer in sorted(offers, key=lambda row: int(row["price_micros"]))[:10]:
        price = Decimal(str(offer["price_micros"])) / Decimal("1000000")
        country = str(offer["country"])
        print(country, names.get(country, country),
              "USD " + format(price, ".6f"), "available:", offer["count"])

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

Run it for the three service entries

Start with the catalog. The program prints the first 20 services and first 10 countries; it still validates your selection against the full returned catalogs.

python raysms_catalog.py
python raysms_catalog.py --service dr
python raysms_catalog.py --service go
python raysms_catalog.py --service tg
Enter fullscreen mode Exit fullscreen mode

To query one country, append --country and an actual ID returned by the country catalog. Do not substitute a phone prefix or country name. The service codes above are the current mapping, not a promise that all three queries will have available offers when you run them.

Read the money and availability fields correctly

price_micros is an integer amount in millionths of a US dollar: 1,000,000 units equals USD 1. The example converts it with Decimal and prints six decimal places. This avoids introducing binary floating-point rounding into the displayed quote.

count is the available quantity reported for that quote. It is not a delivery-success count. An empty items list means that this selection currently has no offers; reading a quote does not reserve a number. Different service-and-country combinations can have different prices and available quantities.

Availability, price and acceptance are separate checks. A returned quote establishes what the catalog reports at that moment. It does not prove that a later purchase will succeed or that OpenAI, Google or Telegram will accept that number and deliver a message. Use a number only where the target service permits its type and your intended use.

Treat failures as a reason to pause

The request has a 15-second timeout. On HTTP 429, the script reports Retry-After when supplied and exits. It also exits on a network error, non-JSON response or unexpected response envelope. There is no automatic retry loop.

That makes the example deliberately limited: it is a catalog explorer, not a production purchase worker. If you later implement purchasing, add authentication, a price ceiling and an idempotency key for each intended purchase. An ambiguous provider outcome should lead you to inspect the original order, not silently create another paid order. The developer guide covers that separate workflow:
https://raysms.com/en/developers

Where the dashboard fits

RaySMS offers a web dashboard and API backed by an upstream number provider, a shared USD wallet and order history, four interface languages, registration email verification, and optional authenticator-based two-factor authentication. Payment options appear according to the channels enabled on the site.

The number service is paid; this example is a free catalog query. Check the service and country before ordering. Cancellation eligibility depends on order state and provider confirmation.

Full Python guide: https://raysms.com/en/guides/sms-api-python
Service overview: https://raysms.com/en/
Payment guide: https://raysms.com/en/guides/pricing-payments

Which part would you want documented more explicitly before adding a paid order call: country selection, quote precision, or ambiguous order states?

Disclosure: I operate RaySMS. This article was drafted with AI assistance and checked against the current implementation.

Top comments (0)