G-SMS.

Documentation

Quotas and limits

Here is everything that can refuse, delay or refund a send, with the value that applies today. These are settings, not constants: an administrator can change them, and the API always tells you which one you hit through its error code.

The numbers

LimitValueCode
Requests per second, per API key10RATE_LIMITED · 429
Messages per day, per accountUnlimited by defaultQUOTA_EXCEEDED · 429
Text length1600 charactersTEXT_TOO_LONG · 400
Client reference length64 charactersVALIDATION_ERROR · 400
Page size on GET /v1/sms20 by default, 100 maximum—
Time a message may stay QUEUED24 hoursFAILED · TIMEOUT
Webhook attempt timeout10 seconds—
Webhook retriesUp to 48 hoursEXHAUSTED

Ten requests per second

The limit is enforced per API key with a token bucket: the bucket holds ten tokens and refills continuously at ten per second. A short burst of ten is fine; a sustained rate above ten is not. Over the limit, the API answers immediately:

HTTP/1.1 429 Too Many Requests
Retry-After: 1

{ "code": "RATE_LIMITED", "message": "Trop de requêtes par seconde" }

Nothing is charged and nothing is queued — a rate-limited request never happened. Two consequences worth designing for: send from a queue rather than from a web request, and give each environment its own key so a batch job in staging cannot throttle your production traffic.

// Send a batch without ever tripping the limiter.
async function sendAll(messages) {
  for (const message of messages) {
    let attempt = 0;

    while (true) {
      const res = await post('/v1/sms', message);

      if (res.status !== 429 && res.status !== 503) break; // done, or a real error

      // Retry-After is in seconds; fall back to an exponential delay.
      const wait = Number(res.headers.get('Retry-After') ?? 2 ** attempt);
      await new Promise((resolve) => setTimeout(resolve, wait * 1000));
      attempt += 1;
    }

    await new Promise((resolve) => setTimeout(resolve, 120)); // ~8 requests/second
  }
}

The daily quota

The daily quota is a safety net against a runaway loop, not a commercial cap. It is disabled by default; when it is set, it counts messages per account over the UTC calendar day and returns 429 QUOTA_EXCEEDED once reached — with no Retry-After header, because the reset time is midnight UTC, not a number of seconds. Treat it as a hard stop for the day, not as something to retry in a loop.

The 24-hour lifetime

A message that is still QUEUED after 24 hours is marked FAILED with the reason TIMEOUT, and refunded. An SMS that arrives a day late is worse than no SMS at all: a login code, a delivery notice or an appointment reminder has no value once its moment has passed, so the API stops trying instead of surprising your user.

Billing and refunds

  • You are charged when the API accepts the message — at the 202, not at delivery. The response returns priceXaf and balanceAfterXaf, so you always know what a send cost and what is left.
  • A message that ends FAILED, for any reason, is refunded automatically and exactly once, in the same transaction as the status change. You do not open a ticket, and you cannot be refunded twice for the same message.
  • A duplicate clientReference is never charged again. See idempotency.
  • A rejected request — 400, 402, 429, 503 — costs nothing. In particular OPERATOR_DISABLED is checked before any charge.
  • Every movement appears in the ledger of the console, with its message identifier.
curl 'https://api.sms.gworldship.com/v1/balance' \
  -H 'Authorization: Bearer gsk_your_api_key'

{ "balanceXaf": 4275 }

A new account is credited with XAF 100 once its phone number is verified — roughly twenty messages to Orange or MTN, enough to finish an integration before paying anything.

What you can send, and to whom

  • Cameroonian mobile numbers only: +2376XXXXXXXX, 2376XXXXXXXX or 6XXXXXXXX.
  • A prefix outside the ART numbering plan is not rejected: the message goes through the default route, billed XAF 10 per segment. Check any number with the carrier lookup.
  • 1600 characters is the ceiling for one request, not one segment. A long text is split and billed per segment — see how segments are counted.
  • No custom sender name: the recipient sees the number of the SIM. G-SMS carries transactional traffic, not marketing campaigns.

Retention

The body of a message is erased 90 days after it was sent. Its metadata — recipient, operator, segments, price, status — is kept, because it is what your invoices and your statistics are built on. Keep the text on your side if you need it longer than that.

Ready to send your first SMS?

Create an account, get 100 FCFA of credit and an API key straight away.

Create account