Skip to main content

SignageStudio API Reference

Build Powerful Integrations

The SignageStudio REST API enables developers to programmatically manage content, players, schedules, and campaigns. Integrate digital signage with your existing systems, automate content updates, and build custom applications on top of the SignageStudio platform.

API Overview

Base URL

Production: https://api.signage.me/v1
Sandbox: https://sandbox-api.signage.me/v1

Key Features

FeatureDescription
RESTful DesignStandard HTTP methods, JSON responses
OAuth 2.0Secure authentication
Rate LimitingFair usage protection
WebhooksReal-time event notifications
PaginationEfficient large dataset handling
VersioningStable, predictable updates

Authentication

OAuth 2.0

SignageStudio API uses OAuth 2.0 for authentication. All API requests require a valid access token.

Getting Credentials

  1. Log in to SignageStudio
  2. Navigate to Settings → API & Integrations
  3. Click Create API Application
  4. Note your client_id and client_secret

Token Request

POST https://api.signage.me/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

Response

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write"
}

Using the Token

Include the token in the Authorization header:

GET https://api.signage.me/v1/players
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

API Keys (Simple Authentication)

For simpler integrations, API keys are available:

GET https://api.signage.me/v1/players
X-API-Key: your_api_key_here

Security Note: API keys should only be used for server-to-server communication. Never expose API keys in client-side code.


Rate Limiting

Limits

PlanRequests/MinuteRequests/Day
Free601,000
Pro30010,000
Enterprise1,000100,000

Rate Limit Headers

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1706745600

Handling Rate Limits

When rate limited, the API returns:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 60 seconds."
}

Core Resources

Players

Players are the devices running SignageStudio software.

List Players

GET /v1/players

Query Parameters:

ParameterTypeDescription
statusstringFilter by status: online, offline, all
group_idstringFilter by player group
pageintegerPage number (default: 1)
per_pageintegerItems per page (default: 25, max: 100)

Response:

{
"data": [
{
"id": "player_abc123",
"name": "Lobby Display 1",
"status": "online",
"last_seen": "2026-02-01T14:30:00Z",
"ip_address": "192.168.1.100",
"version": "5.2.1",
"display": {
"resolution": "1920x1080",
"orientation": "landscape"
},
"location": {
"name": "Main Office",
"address": "123 Main St"
},
"group_id": "group_xyz789",
"campaign_id": "campaign_def456",
"created_at": "2025-06-15T10:00:00Z"
}
],
"meta": {
"current_page": 1,
"per_page": 25,
"total_count": 47,
"total_pages": 2
}
}

Get Player

GET /v1/players/{player_id}

Update Player

PATCH /v1/players/{player_id}
Content-Type: application/json

{
"name": "Updated Display Name",
"group_id": "group_newgroup"
}

Player Commands

POST /v1/players/{player_id}/commands
Content-Type: application/json

{
"command": "restart",
"parameters": {}
}

Available Commands:

CommandDescription
restartRestart player software
rebootReboot device
refreshRefresh content
screenshotCapture screenshot
clear_cacheClear local cache

Content

Content includes media files, layouts, and scenes.

List Content

GET /v1/content

Query Parameters:

ParameterTypeDescription
typestringimage, video, layout, scene, widget
folder_idstringFilter by folder
searchstringSearch by name

Response:

{
"data": [
{
"id": "content_abc123",
"name": "Summer Promotion",
"type": "image",
"mime_type": "image/jpeg",
"file_size": 2456789,
"dimensions": {
"width": 1920,
"height": 1080
},
"duration": null,
"thumbnail_url": "https://cdn.signage.me/thumbs/abc123.jpg",
"url": "https://cdn.signage.me/content/abc123.jpg",
"folder_id": "folder_xyz",
"tags": ["summer", "promotion", "retail"],
"created_at": "2026-01-15T09:00:00Z",
"updated_at": "2026-01-20T14:30:00Z"
}
],
"meta": {
"current_page": 1,
"total_count": 234
}
}

Upload Content

POST /v1/content
Content-Type: multipart/form-data

file: [binary]
name: "New Promotion"
folder_id: "folder_xyz"
tags: ["promotion", "2026"]

Response:

{
"id": "content_new123",
"name": "New Promotion",
"type": "image",
"status": "processing",
"upload_url": null,
"created_at": "2026-02-01T15:00:00Z"
}

Delete Content

DELETE /v1/content/{content_id}

Campaigns

Campaigns are playlists that combine content with scheduling.

List Campaigns

GET /v1/campaigns

Create Campaign

POST /v1/campaigns
Content-Type: application/json

{
"name": "February Promotions",
"description": "Monthly promotional campaign",
"schedule": {
"start_date": "2026-02-01",
"end_date": "2026-02-28",
"days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
"start_time": "09:00",
"end_time": "21:00"
},
"items": [
{
"content_id": "content_abc123",
"duration": 10,
"order": 1
},
{
"content_id": "content_def456",
"duration": 15,
"order": 2
}
],
"player_groups": ["group_xyz789"]
}

Assign Campaign to Players

POST /v1/campaigns/{campaign_id}/assign
Content-Type: application/json

{
"player_ids": ["player_abc", "player_def"],
"group_ids": ["group_xyz"]
}

Schedules

Advanced scheduling for content playback.

Create Schedule

POST /v1/schedules
Content-Type: application/json

{
"name": "Lunch Menu",
"campaign_id": "campaign_abc123",
"rules": [
{
"type": "time_range",
"start_time": "11:00",
"end_time": "14:00"
},
{
"type": "days",
"days": ["monday", "tuesday", "wednesday", "thursday", "friday"]
}
],
"priority": 10
}

Schedule Rule Types

TypeParametersDescription
time_rangestart_time, end_timeTime of day
date_rangestart_date, end_dateDate range
daysdays[]Days of week
recurringinterval, unitRecurring pattern
weathercondition, thresholdWeather-triggered
customexpressionCustom logic

Webhooks

Receive real-time notifications for events.

Register Webhook

POST /v1/webhooks
Content-Type: application/json

{
"url": "https://your-server.com/webhook",
"events": ["player.online", "player.offline", "content.updated"],
"secret": "your_webhook_secret"
}

Webhook Events

EventDescription
player.onlinePlayer connected
player.offlinePlayer disconnected
player.errorPlayer reported error
content.createdNew content uploaded
content.updatedContent modified
content.deletedContent removed
campaign.startedCampaign began playing
campaign.endedCampaign completed

Webhook Payload

{
"event": "player.offline",
"timestamp": "2026-02-01T14:30:00Z",
"data": {
"player_id": "player_abc123",
"name": "Lobby Display 1",
"last_seen": "2026-02-01T14:25:00Z"
},
"signature": "sha256=abc123..."
}

Verifying Webhooks

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

Error Handling

Error Response Format

{
"error": {
"code": "invalid_request",
"message": "The request was invalid.",
"details": [
{
"field": "name",
"message": "Name is required"
}
]
}
}

HTTP Status Codes

CodeMeaning
200Success
201Created
204No Content (success, no body)
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict
422Validation Error
429Rate Limited
500Server Error

Common Error Codes

CodeDescription
invalid_requestMalformed request
authentication_requiredMissing auth
invalid_tokenBad/expired token
insufficient_permissionsAccess denied
resource_not_foundEntity not found
validation_errorInvalid data
rate_limit_exceededToo many requests

Code Examples

Python

import requests

API_KEY = "your_api_key"
BASE_URL = "https://api.signage.me/v1"

headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json"
}

# List all players
response = requests.get(f"{BASE_URL}/players", headers=headers)
players = response.json()

for player in players["data"]:
print(f"{player['name']}: {player['status']}")

# Update player content
response = requests.post(
f"{BASE_URL}/players/player_abc123/commands",
headers=headers,
json={"command": "refresh"}
)

JavaScript/Node.js

const axios = require('axios');

const api = axios.create({
baseURL: 'https://api.signage.me/v1',
headers: {
'X-API-Key': 'your_api_key'
}
});

// List players
async function getPlayers() {
const { data } = await api.get('/players');
return data.data;
}

// Upload content
async function uploadContent(file, name) {
const formData = new FormData();
formData.append('file', file);
formData.append('name', name);

const { data } = await api.post('/content', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});

return data;
}

cURL

# List players
curl -X GET "https://api.signage.me/v1/players" \
-H "X-API-Key: your_api_key"

# Create campaign
curl -X POST "https://api.signage.me/v1/campaigns" \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "New Campaign",
"items": [
{"content_id": "content_123", "duration": 10}
]
}'

SDKs and Libraries

Official SDKs

LanguagePackageRepository
Pythonsignage-studioGitHub
JavaScript@signage/studio-sdknpm
PHPsignage/studio-phpPackagist
C#/.NETSignageStudio.SDKNuGet

Installation

# Python
pip install signage-studio

# Node.js
npm install @signage/studio-sdk

# PHP
composer require signage/studio-php

Frequently Asked Questions


Next Steps


API documentation maintained by MediaSignage. For support, contact developers@digitalsignage.com