REST API Reference
Every endpoint of the WakeLink relay, generated from its OpenAPI spec. Paths are absolute; the API lives under /api/v1.
- Base URL
https://wakelink-project.org- Version
- v1.0.0 · OpenAPI 3.1.0
- Endpoints
- 81 in 10 groups
- Machine-readable
- OpenAPI spec
Authenticating requests
Protected endpoints (marked with a lock) take the access token from POST /api/v1/auth/login or your API token (wl_…) in the Authorization header. The browser app uses the httpOnly wl_session cookie instead.
Authorization: Bearer $WAKELINK_TOKENEndpoints
Authentication
Accounts, sign-in, tokens, sessions, 2FA and Telegram linking.
POST/api/v1/auth/register Register new user
Create a new user account. Returns API token for subsequent requests. Username must be unique and start with a letter. Password must contain uppercase, lowercase, and digit.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
usernamerequired | string | Unique username (letters, numbers, underscores) |
email | string | Email address (optional) |
passwordrequired | string | Password (8-128 chars, mixed case, digit required) |
{
"username": "alice",
"password": "Secure1!",
"email": "[email protected]"
}Responses
- 201User created successfully
- 409Username already exists
- 422Validation error
{
"id": "usr_...",
"username": "alice",
"api_token": "wl_..."
}curl -X POST "https://wakelink-project.org/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"Secure1!","email":"[email protected]"}'POST/api/v1/auth/login User login
Authenticate user and return API token. Supports login by username or email.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
usernamerequired | string | Username or email |
passwordrequired | string | User password |
totp_code | string | 6-digit TOTP code (required only if 2FA is enabled) |
{
"username": "alice",
"password": "Secure1!",
"totp_code": "123456"
}Responses
- 200Login successful
- 401Invalid credentials
- 422Validation Error
- 429Too many attempts
{
"access_token": "eyJ...",
"token_type": "bearer",
"user": { "id": "...", "username": "alice", "api_token": "wl_..." }
}curl -X POST "https://wakelink-project.org/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"Secure1!","totp_code":"123456"}'POST/api/v1/auth/session Create WSS sessionRequires authentication
Create a new session token for WebSocket connections. Session tokens: - Valid for 24 hours - Limited to 10,000 requests - Automatically rotated when nearing expiration
Responses
- 200Session created
- 401Authentication required
- 422Validation Error
{
"session_token": "wls_...",
"expires_at": "2026-01-04T12:00:00Z"
}curl -X POST "https://wakelink-project.org/api/v1/auth/session" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/auth/me Get current userRequires authentication
Get information about the authenticated user.
Responses
- 200User info returned
- 401Authentication required
- 422Validation Error
{
"id": "usr_...",
"username": "alice",
"email": "[email protected]",
"api_token": "wl_...",
"telegram_linked": false,
"totp_enabled": false
}curl -X GET "https://wakelink-project.org/api/v1/auth/me" \
-H "Authorization: Bearer $WAKELINK_TOKEN"PUT/api/v1/auth/me Update profileRequires authentication
Update the current user's username and/or email.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
username | string | New username |
email | string | New email address |
{
"display_name": "Alice"
}Responses
- 200Profile updated
- 400Username already taken or invalid input
- 401Authentication required
- 422Validation Error
{ "id": "...", "username": "alice", "display_name": "Alice" }curl -X PUT "https://wakelink-project.org/api/v1/auth/me" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"display_name":"Alice"}'DELETE/api/v1/auth/me Delete accountRequires authentication
Permanently delete the current user account and all associated data.
Responses
- 200Account deleted
- 401Authentication required
- 422Validation Error
{
"message": "Account deleted"
}curl -X DELETE "https://wakelink-project.org/api/v1/auth/me" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/logout Logout userRequires authentication
Invalidate all sessions for the current user. Note: API token remains valid. To fully revoke access, regenerate the API token via /api/v1/auth/regenerate-token.
Responses
- 200Logged out successfully
- 401Authentication required
- 422Validation Error
{
"message": "Logged out"
}curl -X POST "https://wakelink-project.org/api/v1/auth/logout" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/auth/sessions List active web sessions (devices)Requires authentication
List the current user's active browser/device sessions, newest first.
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/auth/sessions" \
-H "Authorization: Bearer $WAKELINK_TOKEN"DELETE/api/v1/auth/sessions/{session_id} Revoke a web session (sign out a device)Requires authentication
Revoke one of the current user's sessions by id.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
session_idrequired | path | integer | — |
Responses
- 200Successful Response
- 422Validation Error
curl -X DELETE "https://wakelink-project.org/api/v1/auth/sessions/{session_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/regenerate-token Regenerate API tokenRequires authentication
Generate a new API token, invalidating the old one. Use this if you suspect your token has been compromised.
Responses
- 200Token regenerated
- 401Authentication required
- 422Validation Error
{
"api_token": "wl_..."
}curl -X POST "https://wakelink-project.org/api/v1/auth/regenerate-token" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/refresh-token Refresh API tokenRequires authentication
Generate a new API token, invalidating the old one. Alias for /regenerate-token.
Responses
- 200Token refreshed
- 401Authentication required
- 422Validation Error
{
"api_token": "wl_..."
}curl -X POST "https://wakelink-project.org/api/v1/auth/refresh-token" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/token/rotate Rotate API token with immediate revocationRequires authentication
Generate a new API token and immediately revoke the old one in Redis. Unlike /regenerate-token (which only updates the database hash), this endpoint pushes the old token hash to the Redis revocation list so that any in-flight request still carrying the old Bearer token is rejected before the regular database-propagation delay. Prefer this endpoint over /regenerate-token when you believe the old token may have been compromised.
Responses
- 200Token rotated and old token revoked
- 401Authentication required
- 422Validation Error
{
"api_token": "wl_..."
}curl -X POST "https://wakelink-project.org/api/v1/auth/token/rotate" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/auth/config Get server configuration
Returns public server configuration. No authentication required.
Responses
- 200Successful Response
{
"telegram_enabled": true,
"telegram_bot_username": "wakelink_bot",
"registration_enabled": true,
"version": "1.0.0"
}curl -X GET "https://wakelink-project.org/api/v1/auth/config"POST/api/v1/auth/push/register Register ntfy push topicRequires authentication
Register an ntfy.sh topic for push notifications.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
topicrequired | string | ntfy.sh topic name to subscribe to for push notifications |
{
"topic": "https://ntfy.sh/my-wakelink-alerts"
}Responses
- 204ntfy topic registered
- 401Authentication required
- 422Validation Error
{
"message": "Push topic registered"
}curl -X POST "https://wakelink-project.org/api/v1/auth/push/register" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"topic":"https://ntfy.sh/my-wakelink-alerts"}'POST/api/v1/auth/client-token Issue a per-client (device/session) tokenRequires authentication
Create an independent CLIENT token (sess_) for this device/session. Unlike the MASTER token it is NOT replaced when the MASTER is rotated, so signing in on another client (web/phone) no longer breaks this one. Agent (dev_) tokens are unaffected.
Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/auth/client-token" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/telegram/link-code Generate Telegram link codeRequires authentication
Generate a one-time code to link this account to a Telegram account via the bot.
Responses
- 200Link code generated
- 401Authentication required
- 422Validation Error
- 429Rate limit: wait 5 minutes between codes
- 503Telegram bot not configured
{
"code": "a1b2c3d4e5",
"expires_in": 600
}curl -X POST "https://wakelink-project.org/api/v1/auth/telegram/link-code" \
-H "Authorization: Bearer $WAKELINK_TOKEN"DELETE/api/v1/auth/telegram/link Unlink Telegram accountRequires authentication
Remove the Telegram account association from the current user.
Responses
- 200Telegram account unlinked
- 400No Telegram account linked
- 401Authentication required
- 422Validation Error
{
"message": "Telegram unlinked"
}curl -X DELETE "https://wakelink-project.org/api/v1/auth/telegram/link" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/reset-password Reset password with Telegram code
Reset the account password using a one-time code received via the Telegram bot.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
coderequired | string | Reset code from the Telegram bot |
new_passwordrequired | string | New password |
{
"code": "a1b2c3d4e5",
"new_password": "NewPass2!"
}Responses
- 200Password reset successfully
- 400Invalid or expired reset code
- 422Validation Error
{
"message": "Password reset successfully"
}curl -X POST "https://wakelink-project.org/api/v1/auth/reset-password" \
-H "Content-Type: application/json" \
-d '{"code":"a1b2c3d4e5","new_password":"NewPass2!"}'GET/api/v1/auth/check-telegram-linked Check if user has Telegram linked
Check if a user has Telegram account linked (for password reset feedback).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
emailrequired | query | string | — |
Responses
- 200Returns whether user has Telegram linked
- 404User not found
- 422Validation Error
{
"linked": true,
"telegram_username": "alice_tg"
}curl -X GET "https://wakelink-project.org/api/v1/auth/check-telegram-linked?email=..."POST/api/v1/auth/telegram Login or register with Telegram
Verify Telegram Login Widget data and log in or create an account. For new accounts, returns requires_password=True and a setup_token. Call /auth/complete-setup with that token to set a password.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
idrequired | integer | Telegram user ID |
first_namerequired | string | Telegram first name |
last_name | string | Telegram last name |
username | string | Telegram username |
photo_url | string | Telegram profile photo URL |
auth_daterequired | integer | Unix timestamp of auth (must be < 5 min ago) |
hashrequired | string | HMAC-SHA256 verification hash from Telegram |
{
"id": 123456789,
"first_name": "Alice",
"username": "alice_tg",
"auth_date": 1700000000,
"hash": "abcdef..."
}Responses
- 200Logged in or registered via Telegram
- 401Invalid Telegram auth data
- 422Validation Error
- 503Telegram bot not configured
{
"access_token": "eyJ...",
"user": { "id": "...", "username": "alice", "api_token": "wl_..." }
}curl -X POST "https://wakelink-project.org/api/v1/auth/telegram" \
-H "Content-Type: application/json" \
-d '{"id":123456789,"first_name":"Alice","username":"alice_tg","auth_date":1700000000,"hash":"abcdef..."}'POST/api/v1/auth/complete-setup Complete account setup after Telegram registration
Set a password (and optional email) for a Telegram-registered account.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
setup_tokenrequired | string | Token received from /auth/telegram endpoint |
passwordrequired | string | Password to set for the account |
email | string | Optional email address |
{
"setup_token": "...",
"username": "alice",
"password": "Secure1!"
}Responses
- 200Account setup complete
- 400Invalid or expired setup token
- 422Validation Error
{
"access_token": "eyJ...",
"user": { "id": "...", "username": "alice" }
}curl -X POST "https://wakelink-project.org/api/v1/auth/complete-setup" \
-H "Content-Type: application/json" \
-d '{"setup_token":"...","username":"alice","password":"Secure1!"}'GET/api/v1/auth/telegram/app-login Initiate Telegram OAuth directly for Android
Redirects the Android Custom Tab straight to oauth.telegram.org, bypassing the website. After the user authorises, Telegram redirects to /telegram/app-redirect which issues the wakelink://auth deep link.
Responses
- 302Redirect directly to oauth.telegram.org
- 307Successful Response
- 503Telegram bot not configured
curl -X GET "https://wakelink-project.org/api/v1/auth/telegram/app-login"GET/api/v1/auth/telegram/app-redirect Server-side Telegram redirect callback for Android
Receives Telegram Login Widget auth data via redirect (data-auth-url mode), verifies the HMAC hash, finds or creates the user, then issues a 302 redirect to wakelink://auth?token=...&username=...&server=... so the Android app can pick it up via its deep-link intent filter.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id | query | integer | — |
first_name | query | string | — |
last_name | query | string | — |
username | query | string | — |
photo_url | query | string | — |
auth_date | query | integer | — |
hash | query | string | — |
Responses
- 302Redirect to wakelink://auth deep link on success
- 307Successful Response
- 400Invalid or expired Telegram auth data
- 422Validation Error
- 503Telegram bot not configured
curl -X GET "https://wakelink-project.org/api/v1/auth/telegram/app-redirect"POST/api/v1/auth/telegram/bot-login-init Init bot-based Telegram login
Create a pending login session. The client opens the returned bot_url in Telegram, the bot completes the login, and the client polls /bot-login-poll/{token}.
Responses
- 200Bot login session created
- 503Telegram bot not configured
{
"login_token": "random24chars",
"bot_url": "https://t.me/wakelink_bot?start=botlogin_...",
"expires_in": 300
}curl -X POST "https://wakelink-project.org/api/v1/auth/telegram/bot-login-init"POST/api/v1/auth/telegram/bot-login-poll Poll bot login status
Poll the status of a pending bot-login session. The login token is submitted in the JSON body so it never appears in URLs / access logs. Poll every 2–3 seconds until `status is completed` or the token expires (HTTP 404).
Request body application/json · required
| Field | Type | Description |
|---|---|---|
login_tokenrequired | string | Bot login token issued by /telegram/bot-login-init |
{
"login_token": "random24chars"
}Responses
- 200Login status: pending | completed | expired
- 404Token not found
- 422Validation Error
{
"status": "completed",
"access_token": "eyJ...",
"user": { "id": "...", "username": "alice", "api_token": "wl_..." }
}curl -X POST "https://wakelink-project.org/api/v1/auth/telegram/bot-login-poll" \
-H "Content-Type: application/json" \
-d '{"login_token":"random24chars"}'POST/api/v1/auth/request-telegram-reset Send reset code via Telegram bot
Look up the account by username or email, send a one-time PIN to their linked Telegram account. Always returns 200 to avoid user enumeration.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
username_or_telegramrequired | string | Username, email, or numeric Telegram user ID of the account |
{
"username": "alice"
}Responses
- 200Code sent if account has Telegram linked
- 422Validation Error
{
"message": "Reset code sent via Telegram"
}curl -X POST "https://wakelink-project.org/api/v1/auth/request-telegram-reset" \
-H "Content-Type: application/json" \
-d '{"username":"alice"}'PUT/api/v1/auth/password Change passwordRequires authentication
Change the current user's password. On success the server rotates the user's API token, deletes every active Redis session for the account (forcing all other clients to re-authenticate) and returns the new `api_token` so the caller can keep working without re-logging in. TOTP 2FA configuration is preserved.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
current_passwordrequired | string | Current password for verification |
new_passwordrequired | string | New password |
{
"current_password": "OldPass1!",
"new_password": "NewPass2!"
}Responses
- 200Password changed; new API token returned and all prior sessions revoked
- 400Invalid current password
- 401Authentication required
- 422Validation Error
{
"message": "Password changed",
"api_token": "wl_...",
"sessions_revoked": 3
}curl -X PUT "https://wakelink-project.org/api/v1/auth/password" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"current_password":"OldPass1!","new_password":"NewPass2!"}'POST/api/v1/auth/forgot-password Request email password-reset link
Send a one-time password-reset link to the given email address. Always returns 200 to avoid leaking whether an email is registered.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
emailrequired | string | Registered email address |
{
"email": "[email protected]"
}Responses
- 200Reset link sent if the email exists
- 422Validation Error
- 503Mailer service unavailable
{
"message": "If that email exists, a reset link was sent"
}curl -X POST "https://wakelink-project.org/api/v1/auth/forgot-password" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'GET/api/v1/auth/validate-reset-token Check if email reset token is valid (deprecated — use POST variant)
Deprecated. Passing the reset token in the query string leaks it into server access logs / browser history. Use `POST /validate-reset-token` with the token in the JSON body instead. Kept for backward compatibility.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
tokenrequired | query | string | — |
Responses
- 200Token is valid
- 400Token is invalid or expired
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/auth/validate-reset-token?token=..."POST/api/v1/auth/validate-reset-token Check if email reset token is valid
Non-destructive check — does not consume the token. Token is sent in the JSON body.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
tokenrequired | string | Email reset token from the link |
{
"token": "64hex..."
}Responses
- 200Token is valid
- 400Token is invalid or expired
- 422Validation Error
{
"valid": true
}curl -X POST "https://wakelink-project.org/api/v1/auth/validate-reset-token" \
-H "Content-Type: application/json" \
-d '{"token":"64hex..."}'POST/api/v1/auth/reset-password-email Reset password via email token
Validate the email reset token and set a new password.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
tokenrequired | string | Email reset token from the link |
new_passwordrequired | string | New password |
{
"token": "64hex...",
"new_password": "NewPass2!"
}Responses
- 200Password reset successfully
- 400Invalid or expired token
- 422Validation Error
{
"message": "Password reset successfully"
}curl -X POST "https://wakelink-project.org/api/v1/auth/reset-password-email" \
-H "Content-Type: application/json" \
-d '{"token":"64hex...","new_password":"NewPass2!"}'POST/api/v1/auth/2fa/setup Generate TOTP setup secretRequires authentication
Create a temporary TOTP secret, provisioning URI, and QR code so the authenticated user can enroll an authenticator app.
Responses
- 200Successful Response
- 422Validation Error
{
"secret": "BASE32SECRET...",
"uri": "otpauth://totp/WakeLink:alice?secret=...",
"qr_code": "data:image/png;base64,..."
}curl -X POST "https://wakelink-project.org/api/v1/auth/2fa/setup" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/auth/2fa/enable Enable TOTP 2FARequires authentication
Verify the supplied TOTP code against the setup secret and persist the encrypted secret on the user account.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
coderequired | string | — |
secretrequired | string | — |
{
"secret": "BASE32SECRET...",
"code": "123456"
}Responses
- 200Successful Response
- 422Validation Error
{
"status": "enabled"
}curl -X POST "https://wakelink-project.org/api/v1/auth/2fa/enable" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"secret":"BASE32SECRET...","code":"123456"}'POST/api/v1/auth/2fa/disable Disable TOTP 2FARequires authentication
Verify a current TOTP code and remove the stored TOTP secret from the authenticated account.
Request body application/json · required
{
"code": "123456"
}Responses
- 200Successful Response
- 422Validation Error
{
"status": "disabled"
}curl -X POST "https://wakelink-project.org/api/v1/auth/2fa/disable" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'POST/api/v1/auth/2fa/verify Verify TOTP codeRequires authentication
Check whether the supplied TOTP code matches the authenticated user's currently enabled TOTP secret.
Request body application/json · required
{
"code": "123456"
}Responses
- 200Successful Response
- 422Validation Error
{
"valid": true
}curl -X POST "https://wakelink-project.org/api/v1/auth/2fa/verify" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'Agents
Your ESP32 agents, their wake targets, tokens and wake commands.
GET/api/v1/agents List user agentsRequires authentication
Get all agents registered by the current user.
Responses
- 200Agents list returned
- 401Authentication required
- 422Validation Error
{
"agents": [
{
"id": 1,
"agent_id": "WL35080814",
"name": "Living Room ESP",
"model": "ESP32",
"is_active": true,
"is_online": true,
"online_status": "online",
"last_seen": "2026-01-03T12:00:00Z",
"created_at": "2026-01-01T00:00:00Z",
"request_count": 42
}
],
"total": 1,
"username": "alice",
"plan": "free",
"agents_limit": 1
}curl -X GET "https://wakelink-project.org/api/v1/agents" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/agents Register new agentRequires authentication
Register a new agent for the current user. Free plan: up to 2 agents. Pro plan: up to 5 agents. The agent_token (Aegis key) is managed exclusively by the client and ESP32.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
agent_idrequired | string | Unique agent identifier |
name | string | Human-readable agent name |
model | string | Agent hardware model (e.g. ESP32, ESP8266) |
extra_data | object | Custom metadata for the agent |
e2e_token | string | E2E agent token (Aegis key) — stored encrypted at rest so the owner's other clients can sync it and command the agent |
{
"agent_id": "WL35080814",
"name": "Living Room ESP",
"model": "ESP32"
}Responses
- 201Agent registered successfully
- 400Agent limit reached
- 401Authentication required
- 409Agent ID already exists
- 422Validation Error
{
"id": 1,
"agent_id": "WL35080814",
"name": "Living Room ESP",
"model": "ESP32",
"is_active": true,
"is_online": false,
"created_at": "2026-01-03T12:00:00Z"
}curl -X POST "https://wakelink-project.org/api/v1/agents" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"agent_id":"WL35080814","name":"Living Room ESP","model":"ESP32"}'POST/api/v1/agents/virtual Provision a virtual (emulator) agent — no hardware neededRequires authentication
Create a demo agent backed by the software emulator so the app can be tested without a physical ESP32. Returns everything the client needs to add it (agent_id + E2E agent_token) and everything the hosted emulator needs to come online (dev_ api_token), plus an expiry. Counts against the user's agent limit like any agent.
Responses
- 201Virtual agent provisioned
- 400Agent limit reached
- 401Authentication required
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/agents/virtual" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/agents/{agent_id} Get agent infoRequires authentication
Get detailed information about a specific agent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200Agent info returned
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"id": 1,
"agent_id": "WL35080814",
"name": "Living Room ESP",
"is_online": true,
"online_status": "online",
"last_seen": "2026-01-03T12:00:00Z",
"request_count": 42
}curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN"PATCH/api/v1/agents/{agent_id} Update agentRequires authentication
Update agent name, model, metadata, or active status.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
name | string | Updated agent name |
model | string | Updated agent hardware model |
e2e_token | string | E2E agent token to store/update (encrypted at rest) |
metadata | object | Updated metadata |
is_active | boolean | Enable/disable agent |
{
"name": "Office ESP32",
"model": "ESP32-S3"
}Responses
- 200Agent updated
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"id": 1,
"agent_id": "WL35080814",
"name": "Office ESP32"
}curl -X PATCH "https://wakelink-project.org/api/v1/agents/{agent_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Office ESP32","model":"ESP32-S3"}'DELETE/api/v1/agents/{agent_id} Delete agentRequires authentication
Remove an agent from the user's account.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 204Agent deleted
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"message": "Agent deleted"
}curl -X DELETE "https://wakelink-project.org/api/v1/agents/{agent_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/agents/{agent_id}/prekey-bundle Fetch agent prekey bundle for X3DHRequires authentication
Return the agent's prekey bundle, consuming one one-time prekey (if any).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200Bundle returned (one OPK consumed if available)
- 401Authentication required
- 404Agent or bundle not found
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}/prekey-bundle" \
-H "Authorization: Bearer $WAKELINK_TOKEN"PUT/api/v1/agents/{agent_id}/prekey-bundle Publish agent prekey bundleRequires authentication
Store the agent's PUBLIC X3DH prekey bundle. Relay stores it blindly.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
ik_x_pubrequired | string | X25519 identity public key (64 hex) |
ik_ed_pubrequired | string | Ed25519 identity public key (64 hex) |
spk_pubrequired | string | Signed prekey public (64 hex) |
spk_sigrequired | string | Ed25519 signature over spk_pub (128 hex) |
opk_pubs | string[] | One-time prekey public pool (each 64 hex); consumed one per fetch |
{
"ik_x_pub": "...",
"ik_ed_pub": "...",
"spk_pub": "...",
"spk_sig": "...",
"opk_pubs": [
"..."
]
}Responses
- 200Bundle published
- 401Authentication required
- 404Agent not found
- 422Validation Error
curl -X PUT "https://wakelink-project.org/api/v1/agents/{agent_id}/prekey-bundle" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ik_x_pub":"...","ik_ed_pub":"...","spk_pub":"...","spk_sig":"...","opk_pubs":["..."]}'GET/api/v1/agents/{agent_id}/stats Get agent statisticsRequires authentication
Get detailed usage statistics for an agent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200Agent statistics returned
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"agent_id": "WL35080814",
"total_connections": 15,
"total_requests": 320,
"total_wake_commands": 42,
"first_seen": "2026-01-01T00:00:00Z",
"last_seen": "2026-01-03T12:00:00Z",
"avg_requests_per_day": 106.7
}curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}/stats" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/agents/{agent_id}/wake Send Wake-on-LAN command (not supported via relay)Requires authentication
This endpoint is not functional. Wake-on-LAN commands require Aegis end-to-end encryption: the ESP32 firmware processes only Aegis-encrypted packets and silently drops plain relay messages. The relay never holds the agent secret key, so it cannot construct valid Aegis packets. Use the WakeLink CLI (wakelink wake <agent> --mac AA:BB:CC:DD:EE:FF) or the Android app, which implement Aegis directly and hold the agent key.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
mac_addressrequired | string | Target MAC address |
broadcast_ip | string | Broadcast IP address (optional) |
{
"mac_address": "AA:BB:CC:DD:EE:FF",
"broadcast_ip": "192.168.1.255"
}Responses
- 200Successful Response
- 401Authentication required
- 404Agent not found
- 422Validation Error
- 501Not implemented — wake requires Aegis E2E encryption
{
"message": "Wake command sent to Living Room ESP (MAC: AA:BB:CC:DD:EE:FF)"
}curl -X POST "https://wakelink-project.org/api/v1/agents/{agent_id}/wake" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mac_address":"AA:BB:CC:DD:EE:FF","broadcast_ip":"192.168.1.255"}'POST/api/v1/agents/{agent_id}/activity Update agent activityRequires authentication
Record that a agent is active (updates last_seen timestamp).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 204Activity recorded
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"message": "Activity updated"
}curl -X POST "https://wakelink-project.org/api/v1/agents/{agent_id}/activity" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/agents/{agent_id}/rotate-token Rotate per-agent API tokenRequires authentication
Generate a new agent_token for the specified agent. The old token is immediately invalidated. The new token is returned once — store it securely and send it to the firmware.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200New agent token generated
- 404Agent not found or not owned by you
- 422Validation Error
{
"agent_token": "wla_...",
"message": "Agent token rotated"
}curl -X POST "https://wakelink-project.org/api/v1/agents/{agent_id}/rotate-token" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/agents/{agent_id}/export Export firmware-ready agent configRequires authentication
Export the agent configuration as a JSON object suitable for programming directly into firmware (ESP32) or the CLI client. The response contains all relay-side fields the firmware needs to connect: - agent_id – the unique agent identifier - api_token – the user's API token (used as Bearer authentication with the relay) - server_url – WebSocket relay URL (wss://...) - name – human-readable agent name The Aegis agent_token (shared secret for end-to-end encryption) is managed exclusively by the client and firmware; it is NOT stored on the relay and is therefore not included in this response.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200Agent config exported
- 401Authentication required
- 404Agent not found
- 422Validation Error
{
"relay_url": "wss://relay.example.com",
"agent_id": "WL35080814",
"agent_token": "wla_..."
}curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}/export" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/agents/{agent_id}/e2e-key Fetch the agent's E2E key (owner-only, audited)Requires authentication
Retrieve the stored E2E agent token (Aegis key) for one owned agent. This is an explicit, owner-only endpoint that replaces the previous behavior of returning the token on every list/get/update response (which leaked all agent keys on any bulk read). The token is encrypted at rest and decrypted only here. Interim measure until task 013 (AEGIS-native key sync via Pistis/Keryx) lands; at that point this endpoint becomes the Keryx mailbox fetch and the relay will stop holding the key entirely.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200E2E key returned
- 401Authentication required
- 404Agent not found
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}/e2e-key" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/agents/{agent_id}/targets List an agent's wake targetsRequires authentication
List the saved wake-on-LAN target machines (PCs) for an agent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Responses
- 200Wake targets returned
- 401Authentication required
- 404Agent not found
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/agents/{agent_id}/targets" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/agents/{agent_id}/targets Add a wake targetRequires authentication
Save a wake-on-LAN target machine (name + MAC) under an agent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
namerequired | string | — |
macrequired | string | — |
{
"name": "...",
"mac": "..."
}Responses
- 201Wake target created
- 401Authentication required
- 404Agent not found
- 409A target with this MAC already exists
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/agents/{agent_id}/targets" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"...","mac":"..."}'PATCH/api/v1/agents/{agent_id}/targets/{target_id} Update a wake targetRequires authentication
Rename a wake target or change its MAC address.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
target_idrequired | path | integer | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
name | string | — |
mac | string | — |
{
"name": "...",
"mac": "..."
}Responses
- 200Wake target updated
- 401Authentication required
- 404Agent or target not found
- 409A target with this MAC already exists
- 422Validation Error
curl -X PATCH "https://wakelink-project.org/api/v1/agents/{agent_id}/targets/{target_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"...","mac":"..."}'DELETE/api/v1/agents/{agent_id}/targets/{target_id} Delete a wake targetRequires authentication
Remove a saved wake-on-LAN target from an agent.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
agent_idrequired | path | string | — |
target_idrequired | path | integer | — |
Responses
- 204Wake target deleted
- 401Authentication required
- 404Agent or target not found
- 422Validation Error
curl -X DELETE "https://wakelink-project.org/api/v1/agents/{agent_id}/targets/{target_id}" \
-H "Authorization: Bearer $WAKELINK_TOKEN"Vault
The end-to-end encrypted client vault (opaque to the server).
GET/api/v1/vault Download the user's vaultRequires authentication
Return the client-encrypted vault blob and its version. The server cannot decrypt the blob.
Responses
- 200Vault returned (blob null if none yet)
- 401Authentication required
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/vault" \
-H "Authorization: Bearer $WAKELINK_TOKEN"PUT/api/v1/vault Upload the user's vaultRequires authentication
Store a new client-encrypted vault blob. Uses optimistic concurrency: expected_version must match the stored version.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
expected_versionrequired | integer | — |
blobrequired | string | — |
{
"expected_version": 0,
"blob": "..."
}Responses
- 200Vault stored; new version returned
- 401Authentication required
- 409Version conflict — re-fetch and merge
- 422Validation Error
curl -X PUT "https://wakelink-project.org/api/v1/vault" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"expected_version":0,"blob":"..."}'Limits
Plan limits and current usage.
GET/api/v1/limits Get plan limits and current usageRequires authentication
Return the caller's plan, agent usage and today's wake usage. daily_limit == 0 means unlimited (Pro/premium); daily_remaining is null when unlimited.
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/limits" \
-H "Authorization: Bearer $WAKELINK_TOKEN"Statistics
Public project statistics.
GET/api/v1/stats/ Get public project stats
Return non-sensitive aggregate counters and protocol metadata for public dashboards.
Responses
- 200Successful Response
{
"users": 1234,
"agents": 567,
"version": "1.0.0",
"protocol_version": "1.0",
"open_source": true,
"e2e_encrypted": true
}curl -X GET "https://wakelink-project.org/api/v1/stats/"Releases
Release metadata, artifacts, checksums and update checks.
GET/api/v1/releases/latest Get latest release
Return the newest published WakeLink release that matches the caller's update channel.
Responses
- 200Successful Response
{
"version": "1.0.0",
"date": "2024-01-01",
"changelog": ["Initial release"]
}curl -X GET "https://wakelink-project.org/api/v1/releases/latest"GET/api/v1/releases/list List releases
Return metadata for every published WakeLink release currently known to the relay.
Responses
- 200Successful Response
[
{ "version": "1.0.0", "date": "2024-01-01" }
]curl -X GET "https://wakelink-project.org/api/v1/releases/list"GET/api/v1/releases/{version}/info Get release info
Return metadata for the exact release version requested in the path.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
versionrequired | path | string | — |
Responses
- 200Successful Response
- 422Validation Error
{
"version": "1.0.0",
"date": "2024-01-01",
"changelog": ["..."],
"files": ["android.apk", "firmware.bin", "wakelink-cli.tar.gz"]
}curl -X GET "https://wakelink-project.org/api/v1/releases/{version}/info"GET/api/v1/releases/latest/download/{platform} Download latest release
Resolve the newest release for the requested platform and stream the matching artifact back to the client.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
platformrequired | path | string | — |
arch | query | string | — |
chip | query | string | — |
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/releases/latest/download/{platform}"GET/api/v1/releases/{version}/download/{filename} Download release file
Stream a specific release artifact after validating the version and filename.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
versionrequired | path | string | — |
filenamerequired | path | string | — |
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/releases/{version}/download/{filename}"GET/api/v1/releases/{version}/checksums Get release checksums
Return the published checksum manifest for the requested release version.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
versionrequired | path | string | — |
Responses
- 200Successful Response
- 422Validation Error
{
"android.apk": "sha256:abc123...",
"firmware.bin": "sha256:def456..."
}curl -X GET "https://wakelink-project.org/api/v1/releases/{version}/checksums"POST/api/v1/releases/check Check for updates
Compare a client's current version with the newest release available for its platform.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
current_versionrequired | string | Current installed version |
platformrequired | string | Platform: android or firmware |
chip | string | Chip type for firmware (esp32, esp32s3, etc.) |
architecture | string | ABI for Android (arm64-v8a, etc.) |
{
"version": "0.9.0",
"platform": "android"
}Responses
- 200Successful Response
- 422Validation Error
{
"update_available": true,
"latest_version": "1.0.0"
}curl -X POST "https://wakelink-project.org/api/v1/releases/check" \
-H "Content-Type: application/json" \
-d '{"version":"0.9.0","platform":"android"}'POST/api/v1/releases/notify Notify clients of an available updateRequires authentication
Admin-only. Broadcast an 'update available' push notification (via the configured ntfy updates topic) so clients can trigger an OTA / in-app update. Announces the current latest release, or an explicit version/platform supplied in the request body.
Request body application/json · required
| Field | Type | Description |
|---|---|---|
version | string | Explicit version to announce; defaults to the current latest release |
platform | string | Target platform label shown in the notification (android, firmware, cli, all) |
changelog | string | Optional release notes override; defaults to the release's own changelog |
{
"version": "...",
"platform": "all",
"changelog": "..."
}Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/releases/notify" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"version":"...","platform":"all","changelog":"..."}'Paid beta
Seats and applications for the paid beta.
GET/api/v1/beta/status Paid beta: seats left and whether applications are openRequires authentication
Public numbers; for a signed-in caller also `seat` — the status of their own seat, or null.
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/beta/status" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/beta/apply Apply for a paid seat (accepted automatically while there is room)Requires authentication
Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/beta/apply" \
-H "Authorization: Bearer $WAKELINK_TOKEN"Admin
Operator endpoints; every call needs the admin role.
GET/api/v1/admin/users List usersRequires authentication
Return a paginated list of all WakeLink users for administrative review.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | — |
Responses
- 200Successful Response
- 422Validation Error
{
"users": [{ "id": "...", "username": "alice", "is_admin": false, "created_at": "..." }],
"total": 42,
"page": 1
}curl -X GET "https://wakelink-project.org/api/v1/admin/users" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/admin/audit-logs List audit logsRequires authentication
Return a paginated audit trail so administrators can review privileged actions.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | — |
Responses
- 200Successful Response
- 422Validation Error
{
"logs": [{ "id": "...", "action": "login", "user_id": "...", "ip": "...", "created_at": "..." }],
"total": 1000
}curl -X GET "https://wakelink-project.org/api/v1/admin/audit-logs" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/admin/releases/notify Broadcast release notificationRequires authentication
Send a best-effort push notification about a new release to every user with an ntfy topic configured.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
versionrequired | query | string | Version string, e.g. 1.2.0 |
changelog | query | string | Short release notes |
Responses
- 200Successful Response
- 422Validation Error
{
"notified": 128
}curl -X POST "https://wakelink-project.org/api/v1/admin/releases/notify?version=..." \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/admin/users/{user_id}/promote Promote user to adminRequires authentication
Grant administrative privileges to the specified user account.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
user_idrequired | path | integer | — |
Responses
- 200Successful Response
- 422Validation Error
{
"message": "User promoted to admin"
}curl -X POST "https://wakelink-project.org/api/v1/admin/users/{user_id}/promote" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/admin/users/{user_id}/demote Revoke admin privilegesRequires authentication
Remove administrative privileges from the specified user account.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
user_idrequired | path | integer | — |
Responses
- 200Successful Response
- 422Validation Error
{
"message": "User demoted"
}curl -X POST "https://wakelink-project.org/api/v1/admin/users/{user_id}/demote" \
-H "Authorization: Bearer $WAKELINK_TOKEN"GET/api/v1/admin/overview Users by plan, recent signups and the paid-beta numbersRequires authentication
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/admin/overview" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/admin/users/{user_id}/plan Grant or revoke Pro by handRequires authentication
Parameters
| Name | In | Type | Description |
|---|---|---|---|
user_idrequired | path | integer | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
planrequired | string | — |
expires_at | string | — |
{
"plan": "...",
"expires_at": "..."
}Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/admin/users/{user_id}/plan" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"plan":"...","expires_at":"..."}'POST/api/v1/admin/users/{user_id}/active Disable or re-enable an accountRequires authentication
Parameters
| Name | In | Type | Description |
|---|---|---|---|
user_idrequired | path | integer | — |
Request body application/json · required
| Field | Type | Description |
|---|---|---|
activerequired | boolean | — |
{
"active": false
}Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/admin/users/{user_id}/active" \
-H "Authorization: Bearer $WAKELINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"active":false}'GET/api/v1/admin/beta Paid beta: numbers, seats and the latest paymentsRequires authentication
Responses
- 200Successful Response
- 422Validation Error
curl -X GET "https://wakelink-project.org/api/v1/admin/beta" \
-H "Authorization: Bearer $WAKELINK_TOKEN"POST/api/v1/admin/beta/seats/{user_id}/release Give a paid-beta seat backRequires authentication
Parameters
| Name | In | Type | Description |
|---|---|---|---|
user_idrequired | path | integer | — |
Responses
- 200Successful Response
- 422Validation Error
curl -X POST "https://wakelink-project.org/api/v1/admin/beta/seats/{user_id}/release" \
-H "Authorization: Bearer $WAKELINK_TOKEN"WebSocket
Relay connection statistics. The protocol itself is documented separately.
GET/wss/stats Get websocket stats
Return runtime counters for connected websocket agents and clients.
Responses
- 200Successful Response
curl -X GET "https://wakelink-project.org/wss/stats"Health
Liveness and readiness probes for operators.
GET/health Run health check
Perform a comprehensive health check covering configuration, database connectivity, and process state.
Responses
- 200Successful Response
curl -X GET "https://wakelink-project.org/health"GET/health/live Run liveness probe
Report whether the process is alive enough for the platform to keep it running.
Responses
- 200Successful Response
curl -X GET "https://wakelink-project.org/health/live"GET/health/ready Run readiness probe
Report whether required dependencies are ready before the service accepts traffic.
Responses
- 200Successful Response
curl -X GET "https://wakelink-project.org/health/ready"Error codes
Errors answer with a JSON body whose detail explains the failure; validation errors (422) list each invalid field.
| Status | Meaning |
|---|---|
| 400 | Bad Request — validation error or malformed input |
| 401 | Unauthorized — missing or invalid token |
| 403 | Forbidden — insufficient permissions |
| 404 | Not Found — resource does not exist |
| 409 | Conflict — duplicate agent ID or username |
| 422 | Unprocessable Entity — schema validation failure |
| 429 | Too Many Requests — rate limit exceeded |
| 500 | Internal Server Error |