Developers
API reference
Send SMS from your own apps using the FlyMySMS API.
API key
Authenticates every request to the API below.
Sign in to generate your API key.
Send an SMS
One request, one message, sent immediately.
Endpoint
POST https://flymysms.com/api/v1/messagesAuthentication
Every request needs your API key as a Bearer token. Generate one above - it's shown once, so store it somewhere safe (an environment variable, a secrets manager) rather than in code.
Authorization: Bearer YOUR_API_KEYRequest body
JSON, with two fields:
| Field | Type | Description |
|---|---|---|
| to | string | Recipient phone number. E.164 (+2348012345678) or local format - local numbers are interpreted using your account's default country. |
| message | string | Message text, up to 2000 characters. |
Example request
curl -X POST https://flymysms.com/api/v1/messages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+2348012345678",
"message": "Your OTP is 482913"
}'Response
200 once the message has actually been sent and its outcome is known - this call waits for that, it doesn't just queue the message and return early. A rejected send (e.g. an invalid or unreachable number) returns 422 with the same shape, so check status rather than only the HTTP code.
{
"id": "cmXXXXXXXXXXXXXXXXXXXXXXX",
"status": "SENT",
"to": "+2348012345678",
"segments": 1,
"cost": { "amount": 4.5, "currencyCode": "NGN" }
}On failure, an error object instead:
{
"error": {
"code": "insufficient_balance",
"message": "Wallet balance is insufficient to send this message."
}
}Error codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | missing_api_key / invalid_api_key | No Bearer token, or the key isn't valid/was rotated. |
| 400 | invalid_request / invalid_phone_number | Malformed request body, or the phone number couldn't be parsed. |
| 402 | insufficient_balance | Top up your wallet. |
| 403 | email_not_verified | Verify your account email before sending. |
| 403 | otp_device_required | This account has no active OTP device. Pair one on the Devices page. |
| 429 | rate_limited | More than 60 requests in a minute - back off and retry. |
| 500 | internal_error | Something went wrong on our side - safe to retry. |
Billing
Messages sent through your own paired OTP device are free - included in your device subscription. If your device doesn't pick up a message in time and our platform's own backup device sends it on your behalf instead, that one send is billed from your wallet at your account's current per-segment rate. If a send fails outright, nothing is charged.
Sending OTPs
This endpoint requires an active OTP-mode device on your account - subscribe to one on the Devices page first. Once paired, every message sent through this endpoint is offered to your own always-on phone, no extra parameter needed. Without an OTP device, requests to this endpoint are rejected.
Recipient opt-out
If you use this endpoint to run bulk/campaign-style sends (not just OTPs), we automatically append To opt out: www.flymysms.com/u/... to the message whenever there's room to do so without increasing the SMS segment count - and to a recipient's very first message from your account regardless, even if that costs one extra segment, so every recipient gets a working way to stop receiving your messages. This never affects the message text you send - it's a suffix added after your own content, and only ever removed by the recipient themselves clicking the link. Opting out only stops future campaign-style sends - OTPs and other one-off transactional messages to that number keep working normally.