REST API
Arrivals Board includes a built-in HTTP server that accepts messages via a REST API. Any device on the same local network can post messages to the board using simple HTTP requests.
Enabling the local server
The REST API is served by the Arrivals local server. Make sure it is enabled in Settings > Sources > Local Server before making requests. See Local Server for setup details.
Endpoint¶
POST /api/v1/message
The base URL depends on your device's local network address. You can find the full URL in Settings > Sources > Local Server.
Typical format: http://<device-ip>:<port>/api/v1/message
Headers¶
| Header | Value | Required |
|---|---|---|
Content-Type |
application/json |
Yes |
X-API-Key |
Your API key | Yes |
The API key is generated automatically when you enable the local server. You can view and regenerate it in Settings > Sources > Local Server.
Request body¶
The request body is a JSON object with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
text |
String | Yes | The message text to display on the board. Supports inline formatting. |
sender |
String | No | The sender name shown in the header row. Defaults to "API" if omitted. Also supports inline formatting. |
priority |
String | No | Controls when the message is displayed. Accepts "queue", "next", or "now". Defaults to "queue". See below. |
urgent |
Boolean | No | Legacy field. When true, equivalent to "priority": "now". If both priority and urgent are provided, priority takes precedence. |
indicatorColor |
String | No | Sets the indicator lamp color. Accepts "red", "amber", "green", "off", or a hex color string (e.g., "#FF6600"). Defaults to "off". |
avatar |
String | No | Base64-encoded PNG or JPEG image data for a custom sender avatar. Maximum decoded size: 1 MB. Recommended dimensions: 512×512. |
avatarURL |
String | No | An absolute http or https URL to a PNG or JPEG image for the sender avatar. If both avatar and avatarURL are provided, avatar takes precedence. |
Priority levels¶
| Priority | Behavior |
|---|---|
"queue" |
The message joins the queue in time order. It will be shown when its turn comes. This is the default. |
"next" |
The message jumps to the front of the queue. The current message finishes its display duration, then this message flips in. |
"now" |
The message interrupts the currently displayed message immediately. The reels retarget mid-animation to show the new content. |
Example request body¶
{
"text": "Build #1234 passed all tests.",
"sender": "CI Server",
"priority": "next",
"indicatorColor": "green"
}
Response¶
A successful request returns:
{
"status": "ok"
}
HTTP status code: 200 OK
Error codes¶
| Status code | Meaning | Description |
|---|---|---|
400 |
Bad Request | The request body is missing, malformed, or the required text field is empty. |
401 |
Unauthorized | The X-API-Key header is missing or contains an invalid key. |
429 |
Too Many Requests | Rate limit exceeded. The API allows a maximum of 10 requests per minute. Wait and retry. |
Error responses include a JSON body with a message field:
{
"status": "error",
"message": "Rate limit exceeded. Maximum 10 requests per minute."
}
Code examples¶
cURL¶
curl -X POST "http://192.168.1.42:8080/api/v1/message" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{
"text": "Deployment complete.",
"sender": "Deploy Bot",
"priority": "next",
"indicatorColor": "green"
}'
Python¶
import requests
response = requests.post(
"http://192.168.1.42:8080/api/v1/message",
headers={
"Content-Type": "application/json",
"X-API-Key": "your-api-key-here",
},
json={
"text": "Deployment complete.",
"sender": "Deploy Bot",
"priority": "next",
"indicatorColor": "green",
},
)
print(response.json()) # {"status": "ok"}
JavaScript (fetch)¶
const response = await fetch("http://192.168.1.42:8080/api/v1/message", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "your-api-key-here",
},
body: JSON.stringify({
text: "Deployment complete.",
sender: "Deploy Bot",
priority: "next",
indicatorColor: "green",
}),
});
const data = await response.json();
console.log(data); // { status: "ok" }
OAuth endpoints (Apple TV)¶
On Apple TV, signing in to services like Mastodon requires a secondary device to complete the OAuth flow. Arrivals exposes the following endpoints on the local server to facilitate this process. These are used internally by the QR code authentication system described in QR Authentication and are not intended for direct use.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/auth/mastodon/setup |
Displays the Mastodon sign-in page on a secondary device. |
POST |
/auth/mastodon/register |
Registers the app with the Mastodon instance. |
POST |
/auth/mastodon/complete |
Completes the OAuth flow after the user authorizes on their secondary device. |
GET |
/auth/callback |
Receives the OAuth callback redirect from the Mastodon instance. |
Note
These endpoints are only available on Apple TV and are used exclusively for the QR code sign-in flow. You do not need to call them directly.