SMSGateway

Getting started

SMS Gateway sends and verifies one-time passcodes using your own Android phone as the sender. Your phone runs a small app that stays connected to our platform; whenever your server calls our API to send a code, the message goes out through your phone like a normal text message. Everything below — from creating your account to handling a verification result in your own code — walks through the full journey end to end.

01

Create your account

Register on the home page with your name, email, and a password. This just creates your account — it doesn't hand you an API key or require a device yet. You're signed in automatically afterward.

02

Download the app

Install the companion app on the Android phone you want to use as your SMS sender. This phone is what actually sends the text messages, so it should stay powered on and connected (Wi-Fi or mobile data) continuously.

Request

[Download link — coming soon]
03

Pair your phone

From Dashboard → Devices → "Pair device" you'll get a QR code plus a login/pairing-code pair, valid 15 minutes and single-use. On the phone, first open Settings → Cloud Server and set the API URL to the server address we gave you. Then from the Home screen, toggle "Use remote server" — this opens a Pair Device screen with two ways to fill it in: tap "Scan QR code" and point the camera at the code shown in the dashboard modal, or use the Copy button next to the Login and Pairing code fields and paste each one manually. Once submitted, the phone registers itself and shows up as Active on the Devices page within a few seconds.

04

Grant permissions on the phone

When prompted, grant the SMS and Phone permissions — without these, the app can't actually send text messages. For reliable 24/7 operation, also disable battery optimization for the app (Settings → Battery → find the app → "No restrictions", wording varies by manufacturer) and confirm "Start on boot" is enabled on the app's Home screen, so it recovers automatically if the phone ever restarts. Some manufacturers (e.g. Xiaomi/MIUI) are especially aggressive about killing background apps — if a device keeps going offline, check that manufacturer's own battery/autostart settings specifically, not just the standard Android ones.

05

Generate your API key

From your dashboard, go to API Key → "New key", give it a name (e.g. which server or environment it's for), and copy the value shown. It's displayed only once — if you lose it, generate a new one rather than trying to recover it. You can create more than one key and revoke any of them independently.

06

Authenticate your requests

Every call to /v1/otp/* must include your API key in the X-API-Key header — never in the URL or body. Store it as a server-side secret (an env var), since it authenticates as your app.

In your code

const headers = {
  "Content-Type": "application/json",
  "X-API-Key": process.env.OTP_API_KEY, // the key from step 5
};
07

Send an OTP

Call this when a user needs a code — e.g. before confirming a phone number on signup. The code itself is never returned in the response, only sent by SMS. Hang on to requestId if you want to correlate this send with logs later — you won't need it to verify.

Request

POST /api/v1/otp/send
X-API-Key: <your-api-key>
Content-Type: application/json

{ "phoneNumber": "+15551234567" }

Response

{
  "success": true,
  "requestId": "3f6e...",
  "expiresIn": 300
}

In your code

const res = await fetch(`${API_URL}/v1/otp/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({ phoneNumber }),
});

const { success, expiresIn } = await res.json();
// show the user: "Code sent — expires in ${expiresIn}s"
08

Verify the OTP

Call this with the code the user typed in. Branch on verified in your own code: true means the phone number is confirmed and you can proceed with your app's own logic (create the account, issue your own session, etc.) — false means show attemptsRemaining and let them retry. Codes expire after 5 minutes, allow 5 attempts, and are single-use.

Request

POST /api/v1/otp/verify
X-API-Key: <your-api-key>
Content-Type: application/json

{ "phoneNumber": "+15551234567", "code": "482913" }

Response

// correct code
{ "verified": true }

// wrong code
{ "verified": false, "attemptsRemaining": 4 }

In your code

const res = await fetch(`${API_URL}/v1/otp/verify`, {
  method: "POST",
  headers,
  body: JSON.stringify({ phoneNumber, code }),
});

const { verified, attemptsRemaining } = await res.json();

if (verified) {
  // phone number confirmed — continue your own signup/login flow
} else if (attemptsRemaining > 0) {
  // let the user try again, show attemptsRemaining
} else {
  // out of attempts — prompt them to request a new code
}

Good to know

  • • Phone numbers must be in E.164 format (a leading + and country code).
  • • An invalid or missing API key returns 401 Unauthorized.
  • • A malformed request body returns 400 Bad Request.
  • • After 5 failed verify attempts, the code is invalidated — send a new one to try again.
  • • /v1/otp/send needs an active, paired device to deliver anything — with none registered it fails immediately; with one registered but offline, the call still succeeds but the SMS won't actually go out until the phone reconnects.