Signage device API¶
1. Activate a signage device (public, one-time activation code)¶
The current Android signage device obtains an activation_code by
scanning a QR code, then exchanges it for a long-lived device token
through this endpoint.
POST /api/v1/signage/activate
Content-Type: application/json
Request body:
activation_code: one-time activation code.classroom_id: classroom ID carried in the QR code; used for activation validation.device_code: device code generated locally by Android and uploaded to the backend to identify the physical device. If the classroom already has a recorded device code, this value must match it.device_name: optional device name.app_version: optional signage app version.install_id: optional device installation identifier.
Response:
{
"code": 0,
"message": "success",
"data": {
"token": "device_token_here",
"device": {
"id": 1,
"device_code": "8d0e1cb5-6f74-4d95-b861-3a0c2af18413",
"device_label": "5A203 Signage",
"building": "5A",
"room_number": "203",
"capacity": 60,
"status": "available",
"signage_title": "5A203",
"signage_subtitle": "Digital Signage",
"signage_config": {
"announcements": [
{
"label": "Notice",
"text": "Please keep the classroom clean.",
"type": "warn"
}
]
},
"activated_at": "2026-04-08T10:00:00+08:00",
"token_issued_at": "2026-04-08T10:00:00+08:00",
"last_seen_at": "2026-04-08T10:05:00+08:00",
"activation_code_issued_at": null,
"activation_code_expires_at": null,
"is_bound": true
}
}
}
Notes:
Activation codes are single-use and have an expiration time.
The backend stores only the token hash. The plaintext token is returned only once, after successful activation.
Devices must use
Authorization: Bearer <token>to access signage APIs afterward.
2. Current signage device information (device authentication)¶
GET /api/v1/signage/device
Authorization: Bearer <device_token>
Returns the signage configuration for the classroom bound to the current
token. The signage device does not need to pass classroom_id.
Response:
{
"code": 0,
"message": "success",
"data": {
"id": 1,
"device_code": "SIG-ABC123456789",
"device_label": "5A203 Signage",
"building": "5A",
"room_number": "203",
"capacity": 60,
"status": "available",
"signage_title": "5A203",
"signage_subtitle": "Digital Signage",
"signage_config": {
"announcements": [
{
"label": "Info",
"text": "Device is connected.",
"type": "info"
}
]
},
"activated_at": "2026-04-08T10:00:00+08:00",
"token_issued_at": "2026-04-08T10:00:00+08:00",
"last_seen_at": "2026-04-08T10:05:00+08:00",
"activation_code_issued_at": null,
"activation_code_expires_at": null,
"is_bound": true
}
}
3. Current signage device schedule (device authentication)¶
GET /api/v1/signage/device/schedule
Authorization: Bearer <device_token>
Query:
start_date(YYYY-MM-DD)end_date(YYYY-MM-DD)
Response:
{
"code": 0,
"message": "success",
"data": {
"items": [
{
"start_time": "2026-02-04T08:00:00+08:00",
"end_time": "2026-02-04T09:40:00+08:00",
"course_id": 12,
"course_name": "Calculus",
"course_code": "MATH101",
"teacher_name": "John Smith",
"class_name": "CS 2024",
"sections": [1, 2],
"source": "course_occurrence"
}
]
}
}
Notes:
The backend resolves
SignageDevice.classroom_idfrom the device token.The current signage device displays only schedules generated by the course system and does not merge manual borrowings.
4. Generate signage binding QR code data (admin)¶
POST /api/v1/signage/classrooms/{id}/activation-code
Authorization: Bearer <user_access_token>
Content-Type: application/json
Request body (optional):
expires_in_minutes: activation-code validity period in minutes. Default: 10 minutes.
Response:
{
"code": 0,
"message": "success",
"data": {
"activation_code": "ACT-ABC123456789",
"expires_at": "2026-04-08T10:10:00+08:00",
"qr_payload": {
"base_url": "https://example.com/api/v1/",
"classroom_id": 1,
"activation_code": "ACT-ABC123456789"
}
}
}
Notes:
The current implementation generates a one-time
activation_code. A long-lived device token is issued only after the signage device scans the code and activates successfully.Android signage devices generate and persist
device_codelocally, then upload it to the backend during activation.If a classroom has already been bound to a device and the backend has recorded
device_code, later activations with a different uploadeddevice_codeare rejected.Android signage devices remain compatible with the old QR-code payload that directly binds a
token, but the admin side generates theactivation_codepayload by default.
5. Admin-side signage configuration APIs (admin)¶
The following endpoints let the admin side view or control the signage device for a classroom:
GET /api/v1/signage/classrooms/{id}
GET /api/v1/signage/classrooms/{id}/schedule
PATCH /api/v1/signage/classrooms/{id}/config
POST /api/v1/signage/classrooms/{id}/revoke-token
Example body for PATCH /api/v1/signage/classrooms/{id}/config:
{
"device_label": "5A203 Signage",
"signage_title": "5A203",
"signage_subtitle": "Welcome to Smart Signage",
"announcements": [
{
"label": "Notice",
"text": "Please keep the classroom clean.",
"type": "info"
}
]
}
Important notes:
These are admin-side APIs, not public signage-device APIs.
Current Android signage devices should not directly call
/signage/classrooms/{id}or its/scheduleand/configendpoints.After
revoke-tokenis executed, the old token for the bound device becomes invalid immediately, and the device must scan a QR code again to bind.