API Reference & Quickstart
Introduction
Textko is an open-source platform that allows you to use your Android device as a personal SMS gateway. By installing our app and using our cloud API, you can send and receive text messages programmatically without expensive carrier API costs.
Quick Start
Download Textko App
Register Account
Pair Device
Send SMS
Your first API call
Use your device ID and either a JWT (from login) or an API key. The API base path is /api/v1.
curl
curl -X POST https://api.textko.dev/api/v1/gateway/devices/YOUR_DEVICE_ID/send-sms \
-H "Authorization: Bearer YOUR_JWT_OR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"recipients": ["+251912345678"], "message": "Hello from Textko!"}'JavaScript (fetch)
await fetch('https://api.textko.dev/api/v1/gateway/devices/YOUR_DEVICE_ID/send-sms', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_JWT_OR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ recipients: ['+251912345678'], message: 'Hello from Textko!' }),
});Authentication
The API accepts either a JWT (from login/register) or an API key (from your dashboard). Include one of the following in your requests.
Or use the API key header:
Send Message
Send a single SMS message through a specific device. Use recipients (array of phone numbers) and message (string). Authenticate with a Bearer token or the x-api-key header.
Endpoint: POST /api/v1/gateway/devices/:deviceId/send-sms
curl -X POST https://api.textko.dev/api/v1/gateway/devices/YOUR_DEVICE_ID/send-sms \
-H "Authorization: Bearer YOUR_JWT_OR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": ["+251912345678"],
"message": "Hello from Textko!"
}'Webhooks
Configure a webhook URL in your dashboard. Textko sends a POST request to your URL when SMS events occur (e.g. message received or delivery status updated).
Events
MESSAGE_RECEIVED— Incoming SMS received on a deviceMESSAGE_SENT— Outgoing SMS was sent from the deviceMESSAGE_DELIVERED— Outgoing SMS was deliveredMESSAGE_FAILED— Outgoing SMS failed (includes errorCode and errorMessage)
Delivery
Your endpoint should accept POST requests and return a 2XX status code within about 10 seconds. If we do not receive a successful response, we retry at: 3 minutes, 5 minutes, 30 minutes, 1 hour, 6 hours, 1 day, 3 days, 7 days, 30 days.
Security
Each request includes an X-Signature header: HMAC-SHA256 of the raw JSON payload using your webhook secret. Always verify this signature before processing.
// Node.js: verify X-Signature with crypto.createHmac('sha256', secret).update(JSON.stringify(payload)).digest('hex')Payload examples
Message received:
{"webhookEvent":"MESSAGE_RECEIVED","smsId":"...","sender":"+123456789","message":"...","receivedAt":"...","deviceId":"..."}Message sent / delivered / failed include webhookEvent, smsId, status, recipient, and optionally sentAt, deliveredAt, failedAt, errorCode, errorMessage. See the Webhooks area in your dashboard for full sample payloads.
User Management
User management is an admin-only feature for self-hosted instances. Admins can list users, change roles, and delete users (and their associated devices).
Dashboard
Open /dashboard/admin. Only users with the ADMIN role can access it; others are redirected to the main dashboard.
Roles
ADMIN— Full access, including user managementREGULAR— Standard user
API
All endpoints require an admin JWT in Authorization: Bearer <token>.
GET /api/v1/users— List all users (admin only)PATCH /api/v1/users/:id/role— Body:{"role": "ADMIN" | "REGULAR"}(admin only)DELETE /api/v1/users/:id— Delete user and their devices (admin only)
Creating the first admin
Use the create_admin.sh script in the project root. Ensure the Docker stack is running (e.g. textko-db, textko-api). Edit the script to set ADMIN_EMAIL and ADMIN_PASS, then run ./create_admin.sh. Alternatively, promote an existing user to ADMIN via the API or by updating the role field in the database.