New

Temporary Number S2: choose your operator — AT&T or T-Mobile — and the exact area code, with live stock for every area code. Several services on one number, or a specific number. Try it now →

OfferDeposit bonus: get up to +20% free balance on deposits from $50.Get started →

DaisySMS Alternative: Where to Go Now DaisySMS Has Shut Down

DaisySMS is gone. Its homepage now reads "DaisySMS has shut down on March 26, 2026". New sign-ups and top-ups were switched off on February 24, and only a support email remains. If you relied on it for US verification numbers, or had a script built on its API, you need somewhere else. This page covers what to look for, how SMS Portal compares, and how to move an API integration across call by call.

This page is written by SMS Portal, one of the alternatives. Facts about DaisySMS come from its own shutdown notice and API documentation as of September 2026.

What DaisySMS users actually relied on

DaisySMS was popular for a narrow, specific thing, and a replacement has to match that thing rather than just "sell numbers":

  • Real US mobile numbers, not VoIP, so codes from strict platforms actually arrive.
  • Carrier and area-code filters. Its API took carriers=tmo,vz,att, areas= and even number= for a specific number.
  • Your money back when nothing arrived. Cancelling returned the held amount.
  • A simple API. The SMS-Activate-compatible handler_api.php protocol, with getNumber, getStatus and setStatus.
  • Keeping a number for later with action=keep.

How SMS Portal lines up

What you used on DaisySMSOn SMS Portal
Real US mobile numbersYes: every number is a US carrier line. What non-VoIP means.
Carrier filterYes, AT&T or T-Mobile, on the Temp (s2) server. Verizon is not offered.
Area-code filterYes, on Temp (s2), with live stock per area code shown before you order. Can be a preference or a requirement.
Request a specific numberYes, on Temp (s2) (request-specific-number).
Refund when no code arrivesYes. Cancel before a code arrives and the full price goes back to your balance; unused numbers are refunded automatically at expiry.
Keep a numberRentals of 1, 3, 7, 14 or 30 days, with renewal and auto-renew. Or reuse a one-time number from your order history while it is still available.
APIREST + JSON with a bearer token, plus signed webhooks. Not handler_api compatible (mapping below).
PaymentCrypto deposits.
PricePer service, shown before you order. See pricing.

Two honest differences. First, we are US numbers only, the same as DaisySMS was. If you need other countries, look elsewhere. Second, our API is not a drop-in handler_api.php clone, so an integration needs a small adapter. The rest of this page is that adapter.

Moving a DaisySMS API integration

Every SMS Portal endpoint takes Authorization: Bearer <token> (create one in the panel under API access) and returns JSON:

{ "data": { }, "success": true, "summery": "…" }

Check success, not the HTTP status alone. (summery is spelt that way on purpose; it is the field name.)

There are two one-time servers. Temp (s1) lives under /api/v2/tn101/; Temp (s2) lives under /api/v2/tn102/ and adds the carrier, area-code and specific-number options DaisySMS users will look for.

Call-by-call mapping

DaisySMS (handler_api.php)SMS Portal
action=getBalance → ACCESS_BALANCE:50.30GET /api/v2/account-details → data.balance
action=getNumber&service=… → ACCESS_NUMBER:<id>:<number>POST /api/v2/tn101/request-number with {"service_key": "…"} → data.order_id, data.number
getNumber … &carriers=attPOST /api/v2/tn102/request-number with "carrier": "at&t" or "tmobile". Add "keep_carrier": true to fail instead of falling back to another carrier.
getNumber … &areas=212,305Same endpoint with "area_codes": "212,305". Add "lock_area_code": true to make it strict. Stock: GET /api/v2/tn102/get-area-stock?service_key=…
getNumber … &number=…POST /api/v2/tn102/request-specific-number with number and service_key
getNumber … &max_price=…No equivalent. Prices are fixed per service and listed by get-services, so check before you order.
action=getStatus&id=… → STATUS_WAIT_CODEGET …/get-number-details?order_id=…. The code field is null while waiting.
→ STATUS_OK:<code>The code field is set: pin on s1, code on s2. The full text is in message.
setStatus&status=8 → ACCESS_CANCELPOST …/reject-number with {"order_id": …}. On s2 this works from five minutes after purchase; before that it answers 409 with data.retry_after_seconds.
setStatus&status=6 (done)Nothing to call. An order that received its code is complete.
action=keepRent instead: POST /api/v2/rental/request-number. Or POST …/reuse-number to get a past number again.
Service listGET /api/v2/tn101/get-services or /tn102/get-services, which also return prices and surcharges.

Error strings

DaisySMSSMS Portal
BAD_KEYHTTP 401, success: false
NO_MONEYHTTP 400, success: false, with the reason in summery
NO_NUMBERSHTTP 400, success: false. On s2, check get-area-stock first, or relax lock_area_code.
MAX_PRICE_EXCEEDEDNot applicable: no bidding
NO_ACTIVATIONHTTP 404 on get-number-details
Validation problemsHTTP 422, field errors keyed by name in data

A drop-in adapter

If your code is full of getNumber and getStatus calls, the least disruptive migration is a small shim with the same shape. In Python:

import os

import requests

BASE = "https://smsportal.io/api/v2"
HEADERS = {"Authorization": f"Bearer {os.environ['SMSPORTAL_TOKEN']}"}


class SmsPortalError(Exception):
    pass


def _call(method, path, **kwargs):
    body = requests.request(method, f"{BASE}{path}", headers=HEADERS, timeout=30, **kwargs).json()
    if not body.get("success"):
        raise SmsPortalError(body.get("summery") or "request failed")
    return body["data"]


def get_balance():
    return _call("GET", "/account-details")["balance"]


def get_number(service, carrier=None, areas=None):
    """Like DaisySMS getNumber. Returns (order, number)."""
    if carrier or areas:
        payload = {"service_key": service}
        if carrier:
            payload["carrier"] = {"att": "at&t", "tmo": "tmobile"}[carrier]
        if areas:
            payload["area_codes"] = ",".join(areas)
        data = _call("POST", "/tn102/request-number", json=payload)
        return ("s2", data["order_id"]), data.get("number")

    data = _call("POST", "/tn101/request-number", json={"service_key": service})
    return ("s1", data["order_id"]), data.get("number")


def get_status(order):
    """Like DaisySMS getStatus. Returns 'STATUS_WAIT_CODE' or 'STATUS_OK:<code>'."""
    server, order_id = order
    path = "/tn101/get-number-details" if server == "s1" else "/tn102/get-number-details"
    data = _call("GET", path, params={"order_id": order_id})
    code = data.get("pin") if server == "s1" else data.get("code")
    return f"STATUS_OK:{code}" if code else "STATUS_WAIT_CODE"


def cancel(order):
    """Like DaisySMS setStatus=8."""
    server, order_id = order
    path = "/tn101/reject-number" if server == "s1" else "/tn102/reject-number"
    _call("POST", path, json={"order_id": order_id})

Two things to adjust for. service_key values are not the same short codes DaisySMS used, so pull get-services once and build a lookup table from your old codes to ours. And if number comes back empty, read it from get-number-details on the next poll.

Replace polling with webhooks

DaisySMS asked you to poll getStatus no faster than every three seconds. You can keep polling, but it is simpler to register a webhook endpoint in the panel and subscribe to sms.received. Deliveries are signed with HMAC-SHA256 (X-Webhook-Signature, X-Webhook-Timestamp) and retried on failure. The SMS verification testing guide has a verification snippet.

Migration checklist

  1. Create an account and make a small deposit.
  2. Order one number by hand in the panel for the service you use most, and confirm the code arrives.
  3. Create an API token under API access.
  4. Map your old service codes to our service_key values from get-services.
  5. Swap in the adapter above, or port your calls using the mapping table.
  6. Add a webhook for sms.received if you want to stop polling.
  7. Run a handful of real orders before moving your full volume.

Other options

To be fair about it: other services still operating include TextVerified (also US-focused, and also says it uses real carrier numbers), SMSPool and 5SIM (many countries; check each one's number type for your platform). We compared the main ones in best SMS verification services. Price the exact service you need on two or three before depositing anywhere.

FAQ

Is DaisySMS still working?

No. Its site says it shut down on March 26, 2026. Sign-ups and deposits were disabled from February 24, 2026.

Can I get my DaisySMS balance back?

The shutdown notice lists only a support address and does not describe balance refunds. Contact DaisySMS directly; we have no access to DaisySMS accounts.

Is there a DaisySMS-compatible API?

Not here. Our API is REST and JSON rather than handler_api.php. The mapping and adapter above cover every call DaisySMS documented, and most integrations port in an afternoon.

Does SMS Portal offer Verizon numbers?

No. Carrier selection covers AT&T and T-Mobile. Without a carrier filter, orders draw from the whole pool of US mobile numbers.

Recent posts