100MB FREEResidential proxiesClaim
NumberOTP
SDKs

A number and its code, in one call

Official clients for TypeScript, Python, Go and PHP. They retry safely, never buy twice, refresh tokens and tell you exactly what went wrong.

TypeScript / JavaScript

Node 20+, Deno, Bun, Cloudflare Workers, Vercel Edge and browsers. Zero dependencies, ESM and CommonJS.

$ npm install numberotp

Python

Python 3.9+, sync and async clients, fully typed. Built on httpx.

$ pip install numberotp

Go

Go 1.24+, standard library only, iterators for live events.

$ go get github.com/DishantSinghDev2/numberotp-go

PHP

PHP 8.1+, only ext-curl and ext-json. Laravel, Symfony or plain PHP.

$ composer require numberotp/numberotp

Your first number

Set NOTP_API_KEY, then run this. If no SMS arrives in 20 minutes, the number is refunded and the call raises a typed error.

import { NumberOTP } from 'numberotp' const notp = new NumberOTP() // reads NOTP_API_KEY const act = await notp.activations.createAndWait(  { service: 'wa', country: '16' },  { onNumber: n => console.log('Use this number:', n.phoneNumber) },)console.log('Code:', act.otp) // no SMS in 20 min? refunded automatically

Everything else you'll need

Find services by name or website, compare countries, resend, cancel, and follow every event live.

await notp.services.search({ q: 'discord.com' })   // → [{ code: 'ds', name: 'Discord' }]await notp.prices.get({ service: 'wa' })            // price, stock, success rate by country const n = await notp.activations.create({ service: 'tg', country: '187', max_price: 3 })await notp.activations.resend(n.data.id)            // another SMS on the same numberawait notp.activations.cancel(n.data.id)            // no SMS? full refund for await (const e of notp.events.stream()) {        // live events, resumes after drops  if (e.type === 'activation.code_received') console.log(e.data.otp)}

Verify webhooks

Every webhook is signed with HMAC-SHA256. One call checks it, in constant time.

import { verifyWebhook } from 'numberotp' const ok = await verifyWebhook(rawBody, req.headers['x-numberotp-signature'], process.env.NOTP_WEBHOOK_SECRET!)if (!ok) return res.status(401).end()

What every SDK does for you

Safe retries

Network errors, 429 and 5xx are retried with backoff — only where a retry is safe.

Idempotent purchases

Numbers, rentals and top-ups send an Idempotency-Key, so a retry never buys twice.

Typed errors

InsufficientBalanceError, NotFoundError, ActivationClosedError… (…Exception in PHP), each with a stable code.

Token refresh

Sign users in with device or email-code flows; access tokens renew by themselves.

Every endpoint

Generated from the OpenAPI spec, so every API operation exists in every SDK — reseller APIs included.

Your domain

Point the base URL at a reseller white-label domain if you run one.

Keep going