KuruMesaju KuruMesaju
API documentation
JSON API for SMS/OTP to Maldives mobile numbers (+960). User routes use an API key; device routes use a Bearer device token. Outbound jobs are pushed to device webhook_url; device reports results via POST.

For AI agents & code generators

Use these machine-readable URLs (easier than parsing this HTML page):

Phone numbers

Maldives only. You may send numbers in several formats: full international (+9607711097 or 9607711097), national with punctuation (7711-097), or other common local formats. They are normalized to E.164 (+960…) on the server.

The web dashboard is for operators only. Integrators use the HTTP API below with an API key issued by the service operator.

Base URL

https://kurumesaju.rashydh.com/api/v1

User API (API key)

Send the API key as a Bearer token:

Authorization: Bearer YOUR_API_KEY

Rate limits: requests are throttled by client IP, then by your user account for SMS and OTP routes. OTP send/verify share a tighter per-user bucket. Device routes are throttled by IP and then by device id for polling-heavy clients.

POST /sms

Creates an SMS row (status pending). Optional device_id (integer) pins the job to one device. If device_id is omitted and the account has exactly one active device with webhook_url, that device is used automatically. When the resolved device has webhook_url, the server claims the row and POSTs the job to that URL in the same request. Response JSON includes webhook_pushed (boolean).

curl -X POST "https://kurumesaju.rashydh.com/api/v1/sms" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"to\":\"+9607711097\",\"body\":\"Hello\"}"
POST /otp/send

Creates an OTP row and an SMS row with the plaintext code. The OTP row stores sms_message_id linking to that SMS. The SMS leg uses the same device assignment and webhook rules as POST /sms. Response JSON includes otp_id, sms_message_id, expires_at, and webhook_pushed (boolean).

curl -X POST "https://kurumesaju.rashydh.com/api/v1/otp/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"phone\":\"+9607711097\"}"

Optional JSON keys: device_id (integer), ttl_minutes (1–60, default 10).

POST /otp/verify
curl -X POST "https://kurumesaju.rashydh.com/api/v1/otp/verify" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"phone\":\"+9607711097\",\"code\":\"123456\"}"
Device API (device token)

Use the device token shown once in the Devices screen, same Bearer style. In the app you can Edit a device to change its name or webhook URL after creation.

GET /device/jobs/next

Returns the next pending job as JSON (same shape as the outbound webhook), or 204 if none. Locks the row until your phone reports a result.

curl "https://kurumesaju.rashydh.com/api/v1/device/jobs/next" \
  -H "Authorization: Bearer YOUR_DEVICE_TOKEN"
{
  "event": "sms_pending",
  "id": 42,
  "sms_message_id": 42,
  "to": "+9607711097",
  "body": "message text"
}
POST /device/jobs/{id}/result
curl -X POST "https://kurumesaju.rashydh.com/api/v1/device/jobs/1/result" \
  -H "Authorization: Bearer YOUR_DEVICE_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"status\":\"sent\"}"

status must be sent or failed. For failed, add error.

POST /device/ping

Updates last seen time; returns JSON {"ok":true}.

Outbound device webhook

When a pending SMS is assigned to a device that has webhook_url, the server runs a row lock, sets dispatched_at, then POSTs JSON to that URL. If device_id is omitted on POST /sms or POST /otp/send, the server may still assign the row when the account has exactly one active device with webhook_url. Otherwise unassigned rows are not POSTed until a device is chosen (SMS screen: Send now).

POST {device.webhook_url}
Content-Type: application/json

{
  "event": "sms_pending",
  "id": 42,
  "sms_message_id": 42,
  "to": "+9607711097",
  "body": "message text"
}
  • id / sms_message_id: sms_messages.id (integer).
  • to / body: same as stored on the row (to is normalized E.164-style).
  • MacroDroid: use an incoming HTTP trigger on this URL; parse JSON then Send SMS; then call result endpoint below.
  • If the webhook times out or returns a non-success status, the server may retry with backoff (see GATEWAY_WEBHOOK_* in server config). The SMS row stays claimed; the device can still fetch the job via GET /device/jobs/next if you use polling.
Device-authenticated HTTP

All requests:

Authorization: Bearer DEVICE_TOKEN
  • POST https://kurumesaju.rashydh.com/api/v1/device/ping{"ok":true}. Authenticated device requests refresh last_seen_at at most about every 30 seconds to reduce write load.
  • POST https://kurumesaju.rashydh.com/api/v1/device/jobs/:id/result — JSON {"status":"sent"} or {"status":"failed","error":"…"}. Required after sending; unlocks the row.
  • GET https://kurumesaju.rashydh.com/api/v1/device/jobs/next — Optional. Claims next pending like the webhook path; 204 if empty. When 200, JSON matches the webhook payload (event, id, sms_message_id, to, body).
Result POST
  • 403 — sms_messages.device_id does not match the authenticated device.
  • 422 — not dispatched to this device, or status is no longer pending.