Introduction
The World Text REST API can query account and number information, manage
groups, and send SMS text messages.
This document describes the v2.0 HTTP API served by wthttpgw. It was
corrected against the gateway source rather than the prose documentation;
see api/CHANGES.md for the full list of corrections, each with a
file:line reference into wthttpgw.
Base URL
https://sms.world-text.com/v2.0/
Plain HTTP (http://) is accepted by the gateway for compatibility, but
should not be used: credentials travel in the request, and browser and
mobile clients increasingly block it.
Authentication
Every request must carry an API token in the request header:
Authorization: Bearer <token>
A token is an opaque string issued from the admin console or the customer
portal, and is displayed once, at creation. It is verified server-side
against a SHA-256 digest; the token itself is not stored anywhere.
Interfaces
A token names the interfaces it may be used on. It is not a list of
operations: a credential that can reach an interface can use all of it, and
can send messages, because that is what a token is issued for.
| Interface |
Where the credential may be used |
http |
this HTTP API |
email |
email to SMS, one message per email |
bulk |
the bulk email mailbox, one email for many messages |
A token may carry more than one. A token presented at an interface it does
not carry is rejected with 403, whatever the operation. Empty grants
nothing.
There are no finer permissions by operation or by area. Reading is free and
harmless, so there was nothing worth gating; the boundary that matters is
where a credential can be spent. The one exception is worth stating
plainly: the HLR lookups below are charged, and an http token can call
them without ever sending a message. Issue separate tokens per system and
revoke them individually if that matters.
New interfaces are added over time without changing the token format. An
unknown name is rejected at creation rather than stored and ignored.
Rejections
A missing or malformed header is rejected with 400; an unknown, expired
or revoked token with 401; a valid token that does not carry the interface
it was presented at with 403. All three use the standard error envelope:
{"status":"1","error":"1000","desc":"[RFC6750] The access token is invalid or expired"}
These responses never disclose whether a given token identifier exists.
Transport
Send the header over HTTPS only. The token is a bearer credential: anyone
who observes it can use it.
Response envelope
Every response is JSON (or XML/JSONP, see Response formats) with an HTTP
status code that reflects the outcome.
- Success responses carry
"status": "0".
- Error responses carry
"status", "error" (numeric error code, as a
string) and "desc" (human readable message).
status is a stringified integer: "0" success, "1" permanent failure,
"2"/"3" temporary failure. Numeric fields such as credits, msgid
counts and state are stringified for historical reasons; clients should
parse them rather than compare them as numbers.
Response formats
&jsonp=<callback> wraps the JSON body as <callback>(...);
&xml=true returns <result>...</result> instead
These are supported for every operation but are not described per
operation below.
HTTP method overloading
Every context reads a method query parameter and uses it in place of the
HTTP verb when present, but whether the override is honoured depends on
the context, and this differs between contexts in the same deployment.
Observed on 2026-10-18 against sms2.world-text.com:
| Request |
Result |
Override applied? |
GET /group/contents?method=DELETE |
1302 group not found |
yes |
GET /sms/send?txt=x |
1201 Unknown Command |
no |
PUT /sms/send?txt=x |
1200 Incorrect arguments |
n/a (verb matched) |
Treat the override as unreliable: verify it per operation before relying on
it. Where it does apply, a plain GET with method=DELETE will delete,
which makes destructive operations reachable by link prefetchers and
crawlers. Use real verbs.
Submission rate
Clients should submit no more than 10 messages per second. Accounts that
exceed this may be throttled or suspended. There is currently no
machine-readable rate-limit header, so avoid tight retry loops.
Simulation
&sim runs an operation without sending. In the v2 API, presence of the
parameter is enough: sim=false still simulates. (The v3 JSON API
checks the literal string "true".) Simulation is useful on sms/send,
group/send, hlr/lookup and hlr/mnp.
Delivery receipts
Delivery receipts are POSTed to a URL configured on your account, when a
message reaches a final state. They are not modelled as an OpenAPI
callback because the URL is configured out of band; the fields are
documented in components/schemas/DeliveryReceipt.
Receipt fields: msgid, error, state (ACCEPTD, DELIVRD,
EXPIRED, REJECTD, UNDELIV), date (yymmddhhmm), plus clientref
and e212 when enabled on the account.
Do not poll sms/query for delivery status: that operation is deprecated.
Not covered by this document
- The v1 root API (
/credits, /sendsms, /grouplist, ...).
- The v3 JSON-body API under
/v3.0/.
- Inbound (MO) SMS and the email API (
/v2.0/email).