# XenSMS Documentation Index # Fetch this file for LLM / agent discovery ## Pages - https://xensms.co/docs - https://xensms.co/docs/quickstart - https://xensms.co/docs/api-keys - https://xensms.co/docs/send-sms - https://xensms.co/docs/bulk-sms - https://xensms.co/docs/signatures - https://xensms.co/docs/agent ## Agent integration prompt # XenSMS integration guide (for AI coding agents) You are integrating **XenSMS** — a bulk SMS API for Kenya and beyond. ## Base URL `https://api.xensms.co/api/v1` ## Auth (programmatic / server-side) Use **API key + HMAC signature** on message routes. Do NOT use browser JWT for server integrations. Required headers on `POST /messages/sms` and `POST /messages/bulk/sms`: - `X-API-Key`: user's key (starts with `xensms_`) - `X-Timestamp`: Unix ms string - `X-Nonce`: random 32+ char hex (unique per request) - `X-Signature`: HMAC-SHA256 hex of the signature string below - `Content-Type`: application/json - Use a non-browser User-Agent (e.g. `MyApp/1.0`) Signature string (note trailing newline): ``` METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY_JSON\n ``` - PATH is router-relative: `/messages/sms` or `/messages/bulk/sms` (no /api/v1 prefix) - BODY_JSON: JSON with recursively sorted object keys ## Send single SMS ```http POST https://api.xensms.co/api/v1/messages/sms ``` Body: ```json { "recipient": "+254712345678", "content": "Hello from XenSMS", "senderId": "XENDATA" } ``` ## Send bulk SMS ```http POST https://api.xensms.co/api/v1/messages/bulk/sms ``` Body: ```json { "recipients": ["+254712345678", "+254700000001"], "content": "Your OTP is 1234", "senderId": "XENDATA" } ``` ## Balance ```http GET https://api.xensms.co/api/v1/messages/balance ``` Headers: `X-API-Key` only (no signature on balance). ## Dashboard / human flows - Sign up: https://app.xensms.co/register - API keys UI: https://app.xensms.co/api-keys - Top up credits: https://app.xensms.co/payments (USDT on Celo / USDC on Base) ## Errors - 401: bad key or signature / expired timestamp / nonce replay - 402: insufficient credits - 429: rate limit — backoff and retry ## Node.js signature sketch ```javascript const crypto = require('crypto'); function sign(method, path, ts, nonce, body, apiKey) { const sorted = JSON.stringify(sortKeys(body)); const str = `${method}\n${path}\n${ts}\n${nonce}\n${sorted}\n`; return crypto.createHmac('sha256', apiKey).update(str).digest('hex'); } ``` Implement robust error handling, never log full API keys, and validate E.164 phone numbers before send.