WaterSMS API

Two interfaces over the same account and the same wallet: a clean JSON API, and an SMS-Activate compatible endpoint so existing bots work with a URL swap.

Authentication

Every request carries your API key — find it on the Account page. Send it as a header (preferred) or a query parameter.

X-API-Key: ws_xxxxxxxxxxxxxxxxxxxxxxxx
# or
Authorization: Bearer ws_xxxxxxxxxxxxxxxxxxxxxxxx
# or  ?api_key=ws_xxxx  on the SMS-Activate endpoint

Rate limit: 120 requests per minute per key. Exceeding it returns HTTP 429.

JSON API

Base URL: https://watersms.com/api/v1

GET /balance
{ "balance": 42.50, "currency": "USD" }
GET /services

Prices, live stock per service, and the rental plans.

{
  "country": "US",
  "services": [ { "code": "ig", "name": "Instagram", "price": 1.10, "stock": 14 } ],
  "rentals":  [ { "hours": 24, "label": "24 hours", "price": 6.00 } ],
  "rental_stock": 22
}
POST /activations

Buys one verification. Body: { "service": "ig" }. Charges your balance and holds a number.

{
  "ok": true,
  "activation": {
    "id": 8123, "type": "activation", "number": "+14045551234",
    "service": "ig", "price": 1.10, "status": "waiting",
    "code": null, "expires_at": "2026-09-03 23:41:12"
  }
}
GET /orders/:id

Poll this until code is set. Every message received on the number during the hold is in messages.

{
  "order": {
    "id": 8123, "status": "received", "code": "418302",
    "messages": [ { "sender": "Instagram", "body": "418302 is your Instagram code", "code": "418302", "received_at": "..." } ]
  }
}
POST /orders/:id/complete

You got what you needed — releases the number back to the pool.

POST /orders/:id/cancel

Refunds the full price and releases the number. Only before a code arrives, and not within the first 60 seconds.

POST /orders/:id/retry

Asks for another SMS on the same number (up to twice) and extends the hold by 10 minutes.

POST /rentals

Body: { "hours": 24 }. Holds a number for the window; read its inbox with GET /orders/:id.

GET /orders?limit=50

SMS-Activate compatible mode

Point existing software at https://watersms.com/stubs/handler_api.php. Responses are the same plain-text strings, so most clients need only the base URL changed.

GET /stubs/handler_api.php?api_key=KEY&action=getBalance
    → ACCESS_BALANCE:42.50

GET /stubs/handler_api.php?api_key=KEY&action=getNumber&service=ig&country=12
    → ACCESS_NUMBER:8123:14045551234

GET /stubs/handler_api.php?api_key=KEY&action=getStatus&id=8123
    → STATUS_WAIT_CODE          (nothing yet)
    → STATUS_OK:418302          (code arrived)
    → STATUS_CANCEL             (expired or cancelled)

GET /stubs/handler_api.php?api_key=KEY&action=setStatus&id=8123&status=6   → ACCESS_ACTIVATION  (done)
GET /stubs/handler_api.php?api_key=KEY&action=setStatus&id=8123&status=8   → ACCESS_CANCEL      (cancel + refund)
GET /stubs/handler_api.php?api_key=KEY&action=setStatus&id=8123&status=3   → ACCESS_RETRY_GET   (another code)

GET /stubs/handler_api.php?api_key=KEY&action=getNumbersStatus  → {"ig_0":14,"go_0":9,...}
GET /stubs/handler_api.php?api_key=KEY&action=getPrices        → {"12":{"ig":{"cost":1.10,"count":14}}}

Country is always 12 (USA) — the parameter is accepted and ignored. Service codes come from getPrices or the JSON /services endpoint.

Typical flow

curl -s https://watersms.com/api/v1/activations \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"service":"ig"}'

# poll every 2-3 seconds until "code" is filled in
curl -s https://watersms.com/api/v1/orders/8123 -H "X-API-Key: $KEY"

# release the number when you're finished
curl -s -X POST https://watersms.com/api/v1/orders/8123/complete -H "X-API-Key: $KEY"

If no SMS arrives before the hold expires, the order is cancelled and the charge is reversed automatically — you are never billed for a code you did not receive.

Errors

JSONSMS-ActivateMeaning
bad_keyBAD_KEYKey missing, wrong, or the account is suspended
no_balanceNO_BALANCEWallet balance is below the price
no_numbersNO_NUMBERSNo unburned number free for that service
bad_serviceBAD_SERVICEUnknown or disabled service code
too_soonEARLY_CANCEL_DENIEDCancel attempted within 60 seconds of purchase
code_receivedACCESS_ACTIVATIONCannot cancel — a code already arrived
rate_limitedHTTP 429Over 120 requests in a minute