API Reference
The Relayion API lets you send and receive SMS through Android devices registered to your account. All requests go to:
https://api.relayion.com
All endpoints are versioned under /api/v1/. All responses use the JSON envelope:
// Success
{ "success": true, "data": { ... } }
// Error
{ "success": false, "error": { "message": "...", "code": "MACHINE_CODE" } }Authentication
All API endpoints authenticate with an API key. Pass it as a Bearer token in the Authorization header on every request:
Authorization: Bearer rlyn_your_api_key
Getting an API key
Log in to app.relayion.com, go to Settings → API Keys, and click Create key. The full key is shown exactly once. Copy it immediately and store it securely (e.g. in an environment variable). Only the prefix rlyn_xxxxxxxx is retained in the Relayion Console for identification.
Key scopes
Each API key can be authorized to send from one or more devices and SIM slots via scopes configured in the Relayion Console. Routing defaults to the key's default scope. The optional deviceId and simSlotIndex fields on the outbound endpoint let you override routing per request to any scope the key is authorized for.
For inbound message access, the key automatically scopes queries to the phone numbers in its authorized scopes. If a SIM moves to a different device or slot, inbound history remains accessible without creating a new key.
Device discovery
Retrieve the devices registered to your account with their active SIM slots embedded. Use this to confirm device status, inspect SIM slot details, and select the right device when configuring API key scopes in the Relayion Console.
GET /api/v1/devices
Returns all active devices for the account. Soft-deleted devices are excluded. Read-only.
EXAMPLES
{
"success": true,
"data": [
{
"id": "b1c2d3e4-...",
"name": "Office Phone 1",
"status": "ONLINE",
"isPaired": true,
"pendingSetup": false,
"lastSeenAt": "2026-04-25T08:00:00.000Z",
"sims": [
{
"id": "c1d2e3f4-...",
"slotIndex": 0,
"phoneNumber": "+639171234567",
"label": "Globe",
"isDefault": true
}
]
}
]
}Only devices where isPaired is true can receive outbound dispatch. Manage devices and label SIM slots from the Relayion Console at app.relayion.com.
Sending SMS
Submit outbound SMS requests via API key auth. The message is pushed to the device over WebSocket. If the device is offline, it is stored as queued and dispatched on reconnect.
POST /api/v1/outbound
| Field | Type | Required | Notes |
|---|---|---|---|
recipientNumber | string | Yes | E.164 format, e.g. +639171234567 |
body | string | Yes | Message text |
deviceId | string | No | Route to a specific authorized device. Must be in the key's scopes. |
simSlotIndex | integer | No | Pin to a specific SIM slot on the specified device. Requires deviceId. |
Routing
Routing defaults to the key's default scope. Pass deviceId to route to a specific authorized device. Pass both deviceId and simSlotIndex to pin to a specific SIM slot on that device. If the target device is offline, the message is stored as QUEUED and dispatched automatically on reconnect.
EXAMPLES
Response (202)
{
"success": true,
"data": {
"id": "g1h2i3j4-5b6c-7d8e-9f0a-1b2c3d4e5f6a",
"accountId": "a1b2c3d4-...",
"deviceId": "b1c2d3e4-...",
"apiKeyId": "e1f2a3b4-...",
"simSlotIndex": 0,
"recipientNumber": "+639171234567",
"body": "Your appointment is confirmed.",
"status": "DISPATCHED",
"createdAt": "2026-04-25T08:00:00.000Z",
"dispatchedAt": "2026-04-25T08:00:00.001Z",
"sentAt": null,
"deliveredAt": null,
"failedAt": null,
"failureReason": null
}
}status is DISPATCHED if the device was online, QUEUED if offline. Status flow: QUEUED → DISPATCHED → SENT → DELIVERED (or FAILED at any stage after dispatch).
Routing errors
| Code | HTTP | When |
|---|---|---|
UNAUTHORIZED_DEVICE | 403 | deviceId specified is not in the key's authorized scopes |
NO_ELIGIBLE_DEVICE | 422 | All devices in the key's scopes are offline or disabled |
GET /api/v1/outbound
List outbound messages. Optional filters: deviceId, recipientNumber, simSlotIndex, status, from (ISO date), to (ISO date). Sorting: sortBy (createdAt | status | recipientNumber, default createdAt), sortOrder (desc | asc, default desc). Returns an array in the same shape as the POST response.
EXAMPLES
GET /api/v1/outbound/:id
Get a single message by ID with its current delivery status. Returns 404 NOT_FOUND if the message does not exist or belongs to a different account.
EXAMPLES
Receiving SMS
Inbound SMS received by a paired device are stored in real time and available for retrieval via the API. For real-time push delivery to your server, see the Webhooks section.
GET /api/v1/inbound
List inbound messages for the bound phone number. Results are automatically pre-scoped to the bound phone number. Only messages received on that number are returned, regardless of which device or SIM slot received them. Optional filters: deviceId, senderNumber, simSlotIndex, from (ISO date), to (ISO date). Sorting: sortBy (createdAt | receivedAt | senderNumber, default createdAt), sortOrder (desc | asc, default desc).
EXAMPLES
{
"success": true,
"data": [
{
"id": "h1i2j3k4-...",
"accountId": "a1b2c3d4-...",
"deviceId": "b1c2d3e4-...",
"simSlotIndex": 0,
"senderNumber": "+639181234567",
"body": "Yes, please confirm my 3pm appointment.",
"status": "RECEIVED",
"receivedAt": "2026-04-25T08:05:00.000Z",
"createdAt": "2026-04-25T08:05:00.000Z"
}
]
}GET /api/v1/inbound/:id
Get a single inbound message by ID. Returns the same shape as a single item above. Returns 404 NOT_FOUND if not found.
EXAMPLES
Conversations
A unified view of all messages (inbound and outbound) exchanged with a specific phone number, sorted oldest first. Use this for conversation threading.
GET /api/v1/conversations/:phoneNumber
The phone number must be URL-encoded (e.g. +63 → %2B63). When called with an API key, results are automatically pre-scoped to the bound phone number. Only inbound messages received on that number and outbound messages sent from that number are returned. All filters are optional and combine as AND. Additional optional filters include deviceId, simSlotIndex, from (ISO date), to (ISO date), and direction (inbound | outbound). Sorting: sortOrder (asc | desc, default asc). Pagination uses page and limit (default 20, max 100). Returns { total: 0, messages: [] } if the phone number has no messages.
EXAMPLES
{
"success": true,
"data": {
"phoneNumber": "+639171234567",
"total": 2,
"messages": [
{
"id": "g1h2i3j4-...",
"direction": "outbound",
"deviceId": "b1c2d3e4-...",
"simSlotIndex": 0,
"simPhoneNumber": "+639171234567",
"body": "Your appointment is confirmed.",
"status": "DELIVERED",
"sentAt": "2026-04-25T08:00:00.000Z",
"deliveredAt": "2026-04-25T08:00:03.000Z",
"createdAt": "2026-04-25T08:00:00.000Z",
"timestamp": "2026-04-25T08:00:00.000Z"
},
{
"id": "h1i2j3k4-...",
"direction": "inbound",
"deviceId": "b1c2d3e4-...",
"simSlotIndex": 0,
"simPhoneNumber": "+639171234567",
"body": "Yes, please confirm my 3pm appointment.",
"status": "RECEIVED",
"receivedAt": "2026-04-25T08:05:00.000Z",
"createdAt": "2026-04-25T08:05:00.000Z",
"timestamp": "2026-04-25T08:05:00.000Z"
}
]
}
}Webhooks
Relayion posts to your registered endpoint in real time when subscribed events occur. Create and manage webhooks from the Relayion Console at app.relayion.com. This section covers what your receiver needs to handle.
Event types
| Event | When it fires |
|---|---|
inbound.received | An inbound SMS was received by the device and stored |
outbound.queued | An outbound request was accepted while the device was offline |
outbound.dispatched | The send instruction was delivered to the device via WebSocket |
outbound.sent | The device confirmed the SMS was submitted to the carrier |
outbound.delivered | The device received a delivery receipt from the carrier |
outbound.failed | The device reported the SMS failed to send |
inbound.* or all outbound.*. Mixing categories is rejected with 422 MIXED_EVENT_CATEGORIES.Signature verification
Every webhook request includes an X-Relayion-Signature header: the HMAC-SHA256 of the raw request body using your webhook secret, encoded as a hex string. Always verify this before processing.
Important: Always verify against the raw body bytes before JSON parsing. Re-serializing parsed JSON can change whitespace or key order and will produce a different hash.
Payload shapes
The inbound.received payload has two forms depending on the includeBody setting on your webhook (configured in the Relayion Console). When includeBody is disabled (the default), the message body is omitted from the event. Use GET /api/v1/inbound/:id with the id from the payload to retrieve the full message on demand. Enable includeBody only if your endpoint and log infrastructure are appropriate for storing message content. The body is transmitted on every delivery attempt and retry.
// inbound.received, includeBody off (default)
{
"event": "inbound.received",
"timestamp": "2026-04-07T10:00:00Z",
"data": {
"id": "<inboundMessageId>",
"deviceId": "<deviceId>",
"senderNumber": "+639171234567",
"simSlotIndex": 0,
"simPhoneNumber": "+639171234567",
"receivedAt": "2026-04-07T10:00:00Z"
}
}
// inbound.received, includeBody on
{
"event": "inbound.received",
"timestamp": "2026-04-07T10:00:00Z",
"data": {
"id": "<inboundMessageId>",
"deviceId": "<deviceId>",
"senderNumber": "+639171234567",
"body": "Yes, confirmed.",
"simSlotIndex": 0,
"simPhoneNumber": "+639171234567",
"receivedAt": "2026-04-07T10:00:00Z"
}
}
// outbound.queued
{
"event": "outbound.queued",
"timestamp": "2026-04-07T10:00:00Z",
"data": {
"id": "<messageId>",
"recipientNumber": "+639171234567",
"status": "queued",
"createdAt": "2026-04-07T10:00:00Z"
}
}
// outbound.dispatched
{
"event": "outbound.dispatched",
"timestamp": "2026-04-07T10:00:01Z",
"data": {
"id": "<messageId>",
"recipientNumber": "+639171234567",
"status": "dispatched",
"dispatchedAt": "2026-04-07T10:00:01Z"
}
}
// outbound.sent
{
"event": "outbound.sent",
"timestamp": "2026-04-07T10:00:02Z",
"data": {
"id": "<messageId>",
"recipientNumber": "+639171234567",
"status": "sent",
"sentAt": "2026-04-07T10:00:02Z"
}
}
// outbound.delivered
{
"event": "outbound.delivered",
"timestamp": "2026-04-07T10:01:00Z",
"data": {
"id": "<messageId>",
"recipientNumber": "+639171234567",
"status": "delivered",
"deliveredAt": "2026-04-07T10:01:00Z"
}
}
// outbound.failed
{
"event": "outbound.failed",
"timestamp": "2026-04-07T10:00:05Z",
"data": {
"id": "<messageId>",
"recipientNumber": "+639171234567",
"status": "failed",
"failedAt": "2026-04-07T10:00:05Z",
"failureReason": "No signal"
}
}Rate limits
Outbound SMS delivery is controlled by a per-device message bucket. Each device has a burst capacity (messages it can dispatch in a short window) and a sustained rate (how many messages are added back per minute for steady delivery). When the bucket is depleted, requests queue automatically. No error is returned and no message is dropped. Messages are delivered as soon as the bucket refills.
| Plan | Burst capacity | Sustained rate | Monthly cap |
|---|---|---|---|
| Free | 5 messages | 1 / min | 500 messages |
| Starter | 50 messages | 20 / min | None |
| Pro | 100 messages | 50 / min | None |
| Enterprise | Custom | Custom | None |
The Free plan enforces a hard monthly cap of 500 outbound messages per calendar month. When that cap is reached the API returns 429 Too Many Requests:
{
"success": false,
"error": {
"message": "Monthly message limit reached.",
"code": "MONTHLY_LIMIT_EXCEEDED"
}
}Paid plans have no monthly message cap. Enterprise plans have custom burst capacity and sustained rates. Contact sales@relayion.com to discuss your requirements.
n8n
The Relayion n8n community node lets you integrate Relayion SMS into any n8n workflow. Install it from n8n's community nodes panel, then send messages, query outbound and inbound history, browse conversation threads, list devices, and trigger workflows automatically on SMS events.
By default, the workflow routes through the key's default scope. Use the optional deviceId and simSlotIndexfields on the Send SMS operation to target a specific authorized device or SIM slot. The credential's Test button calls GET /api/v1/devices to verify the key is valid.
Installation
In your n8n instance, go to Settings > Community Nodes > Install, enter the package name below, and restart n8n when prompted.
n8n-nodes-relayion
Credentials
Create a Relayion API credential in n8n with these three fields:
| Field | Required | Notes |
|---|---|---|
API Key | Yes | Bearer token, format rlyn_.... Found in the console under API Keys. |
Base URL | Yes | Default https://api.relayion.com. Change only for self-hosted installs. |
Webhook Secret | No | Required only when using the Relayion Trigger node. See Trigger node setup below. |
Operations
The node covers four resources:
Outbound Message
| Operation | Description | Notes |
|---|---|---|
| Send SMS | Submit an outbound SMS to a recipient number. | |
| Get | Retrieve a sent message and its delivery status. | Searchable dropdown or direct ID entry. |
| List | List sent messages with optional filters. | Filters: status, recipient, date range. Sorting: created date, recipient number, status. |
Inbound Message
| Operation | Description | Notes |
|---|---|---|
| Get | Retrieve a specific received message. | Searchable dropdown or direct ID entry. |
| List | List received messages with optional filters. | Filters: sender, date range, SIM slot. Sorting: created date, received date, sender number. |
Conversation
| Operation | Description |
|---|---|
| Get | Get a unified thread of all messages (sent and received) with a phone number, sorted by date. |
Device
| Operation | Description |
|---|---|
| List | List devices registered to this API key's account, with SIM information. |
Simplify toggle
Get and List operations for Outbound and Inbound messages include a Simplify toggle (on by default). When on, the response is trimmed to the most useful fields. When off, the full API response is returned.
Trigger node setup
The Relayion Trigger starts a workflow when Relayion fires a webhook event. Setup is a one-time manual step — the trigger does not auto-register with Relayion.
- Add a Relayion Trigger node to your workflow and activate it. n8n displays a webhook URL.
- In the Relayion console go to Settings > Webhooks > Create. Paste the URL, select the events you want to subscribe to, and save.
- Copy the secret shown after creation. It is shown only once.
- Paste the secret into the Webhook Secret field of your Relayion API credential in n8n.
Trigger events
| Event | Description |
|---|---|
inbound.received | An SMS was received on your device. |
outbound.queued | An outbound SMS was accepted and queued. |
outbound.dispatched | The send instruction was delivered to the device. |
outbound.sent | The device confirmed the SMS was submitted to the carrier. |
outbound.delivered | A delivery receipt was received from the carrier. |
outbound.failed | The SMS failed to send. |
