Requests and responses

Format

  • HTTPS only. Send JSON with Content-Type: application/json; responses are always JSON.
  • Times are ISO 8601 in UTC. IDs are opaque strings with a prefix (msg_, cmp_, otp_).
  • Money is an object with an exact decimal string: { "amount": "0.0350", "currency": "GHS" }. Never parse it as a float.
  • New fields may be added to responses at any time; ignore ones you don’t know.

Status codes

HTTPMeaning
200OK (or an idempotent replay of an earlier request).
202Accepted for sending — work continues in the background.
400 / 422The request was invalid or the code was wrong. See code and fields.
401Missing or invalid API key.
402Not enough funds in the wallet.
403Not allowed (scope, project state, spending cap).
404Not found in this project and environment.
409 / 410Conflicts with the current state (already verified, expired…).
429Rate limit or cooldown — honour Retry-After.
5xxNopexo error — retry with the same Idempotency-Key.

Idempotency

POST /v1/sms/send, POST /v1/sms/bulk and POST /v1/otp/send accept an Idempotency-Key header (8–100 letters, numbers, - or _). The first request with a key does the work; later requests with the same key in the same project return the original result with status 200 and send nothing. Generate a new key for each logical action, e.g. a UUID.

Pagination

Lists return items and nextCursor. Pass cursor=nextCursor to get the next page; null means you’ve reached the end.

Tracing

Every response has an X-Request-Id header (req_…), repeated as traceId in errors and listed in the dashboard’s Usage page. Nopexo logs the endpoint, status and timing of each request — never bodies, phone numbers or keys.

Versioning

The version is in the path (/v1). Additive changes ship without a new version; breaking changes would ship as /v2, with notice.