Complete guide to integrate SkySMS into your application
Getting Started: Create a free account to get your API key. You'll receive 10 free SMS credits.
Create Free Account →All API requests require authentication using an API key passed in the request header:
X-API-Key: your_api_key_here
Generate API keys from your dashboard after logging in.
/api/v1/sms/send
| Parameter | Type | Required | Description |
|---|---|---|---|
phone_number |
string | Yes | Recipient phone number (e.g., +639123456789) |
message |
string | Yes | SMS content (max 1000 characters) |
priority |
string | No | Priority: normal or high (default: normal) |
use_subscription |
boolean | No | Use subscription instead of credits (default: false) |
use_subscription: true to charge from your subscription daily limit instead of credits. You can also set this per API key from your dashboard — no parameter needed when the toggle is on.
curl -X POST https://smstest.skyio.site/api/v1/sms/send \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+639123456789",
"message": "Hello from SkySMS!"
}'
{ "success": true, "queue_id": 123, "status": "pending", "message": "SMS queued for delivery", "payment_method": "credits", "credits_used": 1, "credits_remaining": 999 }
/api/v1/otp/send
| Parameter | Type | Required | Description |
|---|---|---|---|
phone_number |
string | Yes | Recipient phone number (min 10, max 20) |
use_subscription |
boolean | No | Use subscription instead of credits (default: false) |
curl -X POST https://smstest.skyio.site/api/v1/otp/send \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+639123456789"
}'
/api/v1/otp/verify?phone_number=+639123456789&code=123456
curl -X GET "https://smstest.skyio.site/api/v1/otp/verify?phone_number=%2B639123456789&code=123456" \
-H "X-API-Key: your_api_key"
{ "success": true, "message": "OTP verified successfully" }
/api/v1/sms/send-bulk
| Parameter | Type | Required | Description |
|---|---|---|---|
recipients |
array | Yes | Array of objects with phone_number key (max 1000) |
message |
string | Yes | Message content for all recipients (max 1000 chars) |
priority |
string | No | Priority: normal or high (default: normal) |
use_subscription |
boolean | No | Use subscription instead of credits (default: false) |
use_subscription: true to charge from your subscription daily limit instead of credits. You can also set this per API key from your dashboard — no parameter needed when the toggle is on.
curl -X POST https://smstest.skyio.site/api/v1/sms/send-bulk \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"recipients": [{"phone_number": "+639123456789"}, {"phone_number": "+639987654321"}],
"message": "Hello everyone!"
}'
Fetch your sent messages with optional filters. Use this to sync message status with your system.
/api/v1/sms/messages
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter: pending, sent, failed, queued |
from |
date | Start date (YYYY-MM-DD) |
to |
date | End date (YYYY-MM-DD) |
per_page |
integer | Results per page (max 100) |
curl -X GET "https://smstest.skyio.site/api/v1/sms/messages?status=failed" \
-H "X-API-Key: your_api_key"
/api/v1/sms/messages/failed
/api/v1/sms/messages/resend
curl -X POST "https://smstest.skyio.site/api/v1/sms/messages/resend" \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"unique_message_id": "msg_4a8b2c9d1e3f5a6b"}'
/api/v1/sms/messages/{'{id}'}/resend
/api/v1/sms/messages/bulk-resend
curl -X POST "https://smstest.skyio.site/api/v1/sms/messages/bulk-resend" \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"ids": [123, 456, 789]}'
Two-Way SMS lets you receive replies and reply back through the same phone/SIM that sent the original message.
Access is granted by purchasing 5,000+ credits, having a 6+ month subscription, or by admin manual grant. All endpoints require a valid API key with Two-Way SMS access.
/api/v1/two-way/status
curl -X GET https://smstest.skyio.site/api/v1/two-way/status \
-H "X-API-Key: your_api_key"
{
"success": true,
"data": {
"has_access": true,
"source": "credit_purchase",
"is_permanent": true,
"qualifies_by_credit": true,
"qualifies_by_subscription": false
}
}
/api/v1/two-way/inbound
Paginated inbound SMS messages routed to your account (50/page, newest first).
curl -X GET "https://smstest.skyio.site/api/v1/two-way/inbound?page=1" \
-H "X-API-Key: your_api_key"
/api/v1/two-way/conversations
Paginated conversations (30/page, most recently active first). Each tracks a recipient number, device/SIM, unread count, and last message timestamp.
curl -X GET "https://smstest.skyio.site/api/v1/two-way/conversations" \
-H "X-API-Key: your_api_key"
/api/v1/two-way/conversations/{'{id}'}
Returns the full merged outbound + inbound timeline, oldest to newest. Calling this marks all inbound messages in the conversation as read and resets the unread count.
curl -X GET "https://smstest.skyio.site/api/v1/two-way/conversations/12" \
-H "X-API-Key: your_api_key"
{
"success": true,
"conversation_id": 12,
"phone_number": "09171234567",
"data": [
{ "id": 101, "direction": "outbound", "message": "Hi, your order is ready.", "status": "delivered", "timestamp": "2026-08-30T17:30:00+08:00" },
{ "id": 1, "direction": "inbound", "message": "Thanks! I'll pick it up tomorrow.", "status": "read", "timestamp": "2026-08-30T17:39:00+08:00" }
]
}
/api/v1/two-way/conversations/{'{id}'}/reply
| Parameter | Type | Required | Description |
|---|---|---|---|
message |
string | Yes | Reply message (max 1000 chars) |
idempotency_key |
string | No | Unique key to prevent duplicate replies (max 128 chars) |
idempotency_key to safely retry without double charges.
curl -X POST https://smstest.skyio.site/api/v1/two-way/conversations/12/reply \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"message": "Great, see you tomorrow!",
"idempotency_key": "reply-001"
}'
{
"success": true,
"queue_id": 205,
"status": "pending",
"message": "Reply queued successfully",
"credits_used": 1,
"credits_remaining": 999
}
/api/v1/two-way/inbound/{'{id}'}/read
Marks a single inbound as read and decrements the conversation's unread count. (Viewing a thread already marks all its messages as read.)
curl -X POST https://smstest.skyio.site/api/v1/two-way/inbound/1/read \
-H "X-API-Key: your_api_key"
Send outbound via POST /sms/send — system assigns a phone/SIM and creates a conversation.
Recipient replies to that SIM's number. Android receives it and uploads to the backend.
Backend routes the inbound to your account by matching SIM + phone to your outbound message.
Poll GET /two-way/conversations or use FCM push to get notified.
Open thread with GET /two-way/conversations/{'{id}'} to read the conversation.
Reply with POST /two-way/conversations/{'{id}'}/reply — goes out through the same SIM.
Notes
routing_status = unmatched/ambiguous and not returned by GET /two-way/inbound. Admins resolve them from the admin panel.Violations result in credit penalties. Messages that violate our policy appear as "sent" but are NOT delivered to the recipient.
Rules are automatically enforced on /sms/send and /sms/send-bulk.
| Violation | Penalty | Description |
|---|---|---|
| URL / Links | 10 credits/msg | Any URLs, domains, IPs, shortened links (http, www, bit.ly, etc.) |
| Profanity | 50 credits/msg | Filipino (Tagalog, Bisaya) or English profanity, insults, bullying |
{"success":true,"status":"sent","warning":"Message contained a URL. A 10-credit penalty has been applied and the message was not delivered.","penalty_credits":10,"credits_remaining":90}
| Type | Requests | Period | Scope |
|---|---|---|---|
| Standard | 60 | per minute | Per API Key |
| Burst | 10 | per second | Per API Key |
Best Practices
429 Too Many Requests, check the Retry-After header.| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Invalid parameters |
| 401 | Unauthorized | Invalid API key |
| 402 | Payment Required | Insufficient credits |
| 403 | Forbidden | Access denied |
| 422 | Validation Error | Missing/invalid parameters |
| 429 | Too Many Requests | Rate limit exceeded (60/min) |
| 500 | Server Error | Internal error |