Two ways in, one key (API keys): the SMS-Activate protocol - existing SMS tools work by changing only the address and key - and a JSON API. Downloads: OpenAPI file · Postman collection
1. SMS-Activate protocol closed right now - buying answers an error until it opens
Address https://onlineselling.org/stubs/handler_api.php · parameters api_key and action, GET or POST, plain-text or JSON replies exactly as your tool expects. Country ids are the SMS-Activate ones (187 = USA, 16 = UK …). Add operator=real for US real-SIM (non-VoIP) numbers.
https://onlineselling.org/stubs/handler_api.php?api_key=mk_live_YOURKEY&action=getNumber&service=wa&country=16 → ACCESS_NUMBER:1234:447700900123 https://onlineselling.org/stubs/handler_api.php?api_key=mk_live_YOURKEY&action=getStatus&id=1234 → STATUS_WAIT_CODE … then STATUS_OK:482913
| getBalance | ACCESS_BALANCE:12.40 |
| getNumber / getNumberV2 | service, country, maxPrice, operator=real → ACCESS_NUMBER:id:number (V2: JSON). The price is held and charged only when the code arrives. Errors: NO_NUMBERS, NO_BALANCE, BAD_SERVICE, BAD_COUNTRY, WRONG_MAX_PRICE:price |
| getStatus / getStatusV2 | id → STATUS_WAIT_CODE · STATUS_OK:code · STATUS_WAIT_RETRY:code · STATUS_CANCEL (V2: JSON with the full SMS) |
| getFullSms | id → FULL_SMS:text |
| setStatus | id + status: 1 ready → ACCESS_READY · 3 another SMS → ACCESS_RETRY_GET · 6 done → ACCESS_ACTIVATION · 8 cancel → ACCESS_CANCEL (EARLY_CANCEL_DENIED in the first minutes) |
| getActiveActivations | your numbers still open |
| getPrices · getServicesList · getCountries | catalog, with our prices and stock (country, service optional) |
| getExtraActivation | activationId → the same number again for a new code |
| getRentServicesAndCountries | rent_time (hours), country → rental prices for the nearest length on sale ("full" = any SMS) |
| getRentNumber | service (or full), rent_time, country → {"status":"success","phone":{"id","endDate","number"}}. Paid when assigned. |
| getRentStatus · setRentStatus · getRentList | messages of a rental · 1 finish, 2 cancel + refund (first minutes, before any message) · your active rentals |
Status calls are answered from our own records instantly - poll as often as your limit allows. Too fast → ACCESS_REQUEST_EXCEEDED.
2. JSON API
Base https://onlineselling.org/api/v1 · header Authorization: Bearer mk_live_… (or X-API-Key) · errors {"error":{"code","message"}} with 401, 402 (balance), 404, 422, 429, 503.
| GET /ping | Check the key |
| GET /balance | Wallet balance and money reserved by running orders |
| GET /transactions | Wallet history, newest first limit: max 200 · before: page: next_before of the last answer |
| GET /coins | Coins open for top-ups |
| POST /deposit-address | Your permanent deposit address for a coin {"coin":"usdt-tron"} |
| POST /invoice | Payment page for an exact amount {"amount":25} |
| GET /payments | Your last 50 top-ups |
| GET /sms/countries | Countries with numbers on sale |
| GET /sms/prices | Prices and stock country: country id (187 = USA, 16 = UK ...) · service: service code, e.g. wa · line: otp (one-time, default) or rent · tier: standard (default) or real_sim |
| POST /sms/orders | Take a number for one code (price held, charged only when the code arrives). US real-SIM options (tier real_sim): carrier (at&t, verizon, t-mobile) + keep_carrier, area_codes + lock_area_code, number (10 digits), or services: [codes] for several on one number {"service":"wa","country":16,"tier":"standard","max_price":1.5} |
| GET /sms/us/area-codes | US area codes with numbers free now, for one service service: service code |
| GET /sms/orders | Your one-time orders status: open (default) or all · limit: max 100 |
| GET /sms/orders/{id} | One order with its codes |
| POST /sms/orders/{id}/cancel | Cancel (nothing charged); allowed from cancel_available_at |
| POST /sms/orders/{id}/swap | Another number, same price |
| POST /sms/orders/{id}/another | Another SMS on the same number (where the service allows) |
| POST /sms/orders/{id}/finish | Done with this number |
| POST /sms/rentals | Rent numbers (paid when assigned). Code-link numbers: "type": "link" (valid 5-80+ days, no "days") {"service":"wa","country":16,"days":7,"quantity":1} |
| POST /sms/rentals/{id}/renew | Renew for the same length at today's price (when the rental shows can_renew: true) |
| POST /sms/rentals/{id}/auto-renew | Renew automatically before the end {"on":true} |
| GET /sms/rentals | Your rentals status: active (default) or all |
| GET /sms/rentals/{id} | One rental with its messages and code link |
| GET /sms/rentals/{id}/messages | New messages only after_id: last message id you have |
| POST /sms/rentals/{id}/cancel | Cancel and refund (only where allowed: first minutes, before any message) |
| POST /sms/rentals/{id}/new-link | New code link (the old one stops working) |
| GET /accounts/products | Accounts on sale: price, min / max per order (stock numbers when the shop shows them) category: category address, e.g. hotmail-outlook |
| POST /accounts/orders | Buy accounts (paid from the wallet; the logins are in the reply when delivered at once) {"product_id":123,"quantity":2,"promo":"OPTIONAL"} |
| GET /accounts/orders | Your accounts orders, newest first (without the logins) limit: max 100 · before: page: next_before of the last answer |
| GET /accounts/orders/{ref} | One order with its logins |
| GET /accounts/orders/{ref}/file | The delivered file (tdata / session zip) of an order |
| GET /giftcards | Gift cards on sale with the price of each amount q: search · country: 2-letter country · page: page (100 per page) |
| POST /giftcards/orders | Buy a gift card (the code is in the reply when delivered at once) {"giftcard_id":123,"amount":25,"promo":"OPTIONAL"} |
| GET /esim/packages | eSIM data plans on sale country: 2-letter country · data: GB or unlimited · days: days · page: page (200 per page) |
| POST /esim/orders | Buy an eSIM plan (the LPA activation code is in the reply) {"package_id":123,"promo":"OPTIONAL"} |
| GET /kc/orders/{ref} | One gift card / eSIM order with its code |
| GET /cards/bins | Virtual card types on offer, with fees and load limits |
| POST /cards | Issue a virtual card with a first load ("agree": true = you accept the card terms) {"bin_id":1,"amount":50,"first_name":"Ann","last_name":"Lee","agree":true} |
| GET /cards/{ref} | One card; details=1 adds the live card number, CVV and transactions (limited per hour) details: 1 = live details |
| POST /cards/{ref}/topup | Load more money onto a card {"amount":25} |
| POST /cards/{ref}/freeze | Freeze or unfreeze a card {"action":"freeze"} |
| GET /webhook | Your webhook settings |
| POST /webhook | Set your webhook address and events {"url":"https://example.com/hook","events":["sms.received","order.updated"]} |
| POST /webhook/test | Send a test event now |
curl -X POST https://onlineselling.org/api/v1/sms/orders -H "Authorization: Bearer mk_live_YOURKEY" -H "Content-Type: application/json" -d '{"service":"wa","country":16}'3. Code links and webhooks
Every rental has a code link https://onlineselling.org/api/record?token=… (no key needed; the token is the key). Formats with &type=: json (default), json1, json2, json3, txt, txt1, txt2. One link can cover many numbers (My rentals). POST /sms/rentals/{id}/new-link replaces a link.
Webhooks: set on API keys or POST /webhook. Check the signature:
PHP: hash_equals(hash_hmac('sha256', $rawBody, $secret), $_SERVER['HTTP_X_SIGNATURE'])
Python: hmac.compare_digest(hmac.new(secret.encode(), raw_body, 'sha256').hexdigest(), request.headers['X-Signature'])4. Social growth panel API (v2) closed right now - buying answers an error until it opens
Address https://onlineselling.org/api/v2 · POST key (your API key) and action · the same format as Perfect Panel API v2, so panel scripts and resellers' sites work by changing only the address and key. Prices and the balance are in USD.
curl -X POST https://onlineselling.org/api/v2 -d key=mk_live_YOURKEY -d action=add -d service=123 -d link=https://instagram.com/p/abc -d quantity=1000
→ {"order": 12345}| services | Every service: service, name, type, category, rate (per 1000), min, max, dripfeed, refill, cancel |
| add | New order -> {"order": 12345} service: service id · link: the page / post · quantity: how many · runs: drip-feed: runs (optional) · interval: drip-feed: minutes between runs · comments: custom comments / usernames / hashtags / keywords: one per line · promo: promo code (optional) · username: subscriptions: the profile · min: subscriptions: per post from · max: subscriptions: per post up to · posts: subscriptions: new posts · old_posts: subscriptions: old posts · delay: subscriptions: minutes · expiry: subscriptions: d/m/Y |
| status | charge, start_count, status, remains, currency (subscriptions: status, expiry, posts, orders) order: order id · orders: or up to 100 ids: 1,2,3 |
| refill | Ask for a refill -> {"refill": id} order: order id · orders: or several: 1,2,3 |
| refill_status | Pending / In progress / Completed / Rejected refill: refill id · refills: or several: 1,2,3 |
| cancel | Cancel where the service allows it orders: order ids: 1,2,3 |
| balance | Your wallet balance in USD |
Errors come back as {"error": "..."}. Too fast (per-key limits on API keys) → HTTP 429 with an error.
Try it
Only read-only calls here - nothing is bought.