{ "openapi": "3.0.3", "info": { "title": "LiteNet API", "description": "LiteNet is a free community PBX based on FreePBX. This API allows you to\nmanage your extension, access voicemails, view conferences, and interact\nwith the LiteNet PBX programmatically.\n\n**Authentication:** Most endpoints require a Bearer token obtained via\nDiscord OAuth. Pass it in the `Authorization` header:\n`Authorization: Bearer *** version: \"1.0.0\"\n", "contact": { "name": "LiteNet", "url": "https://litenet.tel" } }, "servers": [ { "url": "https://api.litenet.tel", "description": "Production API" }, { "url": "http://localhost:3001", "description": "Local development" } ], "paths": { "/extensions/me": { "get": { "summary": "Get current extension", "description": "Returns the authenticated user's extension details, including their Discord profile and PBX device configuration.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "Extension details", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExtensionDetails" } } } }, "401": { "description": "Unauthorized" } } } }, "/extensions/me/devicestatus": { "get": { "summary": "Get device registration status", "description": "Returns whether the user's SIP device is currently registered with the PBX. Polled every 5 seconds on the dashboard.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "Device status", "content": { "application/json": { "schema": { "type": "object", "properties": { "extension": { "type": "string", "description": "The extension number", "example": "1010" }, "deviceState": { "type": "string", "description": "Human-readable state (e.g. \"Registered\", \"In use\")", "example": "In use" }, "activeChannels": { "type": "string", "nullable": true, "description": "Active channel info or null if none", "example": null } } } } } } } } }, "/extensions/me/calls": { "get": { "summary": "List active calls", "description": "Returns all currently active calls for the authenticated user's extension. Polled every 5 seconds on the dashboard.", "tags": [ "Calls" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "List of active calls", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ActiveCall" } } } } } } }, "delete": { "summary": "Hangup all calls", "description": "Hangs up every active call for the user's extension.", "tags": [ "Calls" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "All calls hung up", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Status message", "example": "Successfully requested termination for 1 call(s) for extension 1010." }, "terminatedChannels": { "type": "array", "description": "List of terminated channel IDs", "items": { "type": "string" }, "example": [ "PJSIP/1010-00000002" ] } } } } } }, "401": { "description": "Unauthorized" } } } }, "/extensions/me/callme": { "post": { "summary": "Call me", "description": "Triggers the PBX to call the user's extension. Supports music on hold and echo test modes.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "parameters": [ { "in": "query", "name": "mode", "required": true, "schema": { "type": "string", "enum": [ "hold", "echo" ] }, "description": "`hold` \u2014 play music on hold\n`echo` \u2014 echo test (play back what you say)\n" }, { "in": "query", "name": "callerId", "required": false, "schema": { "type": "string" }, "description": "Custom caller ID to display (defaults to the extension number)" }, { "in": "query", "name": "autoAnswerMode", "required": false, "schema": { "type": "string" }, "description": "Auto-answer mode for the call" } ], "responses": { "200": { "description": "Call initiated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Status message", "example": "Successfully initiated hold call to extension 1010." } } } } } } } } }, "/extensions/me/resetsecret": { "post": { "summary": "Reset SIP secret", "description": "Resets the SIP password for the extension. Returns the new secret once \u2014 it cannot be retrieved again.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "Secret reset", "content": { "application/json": { "schema": { "type": "object", "properties": { "newSecret": { "type": "string", "description": "The new SIP secret (displayed once)", "example": "aB3xK9mP2qR7" } } } } } } } } }, "/extensions/me/dnd": { "get": { "summary": "Get Do Not Disturb status", "description": "Returns whether Do Not Disturb is currently enabled.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "DND status", "content": { "application/json": { "schema": { "type": "object", "properties": { "extension": { "type": "string", "description": "The extension number", "example": "1010" }, "dndStatus": { "type": "boolean", "description": "Whether DND is enabled", "example": false } } } } } } } }, "post": { "summary": "Toggle Do Not Disturb", "description": "Enables or disables Do Not Disturb for the extension.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "dndStatus" ], "properties": { "dndStatus": { "type": "boolean", "description": "true to enable, false to disable" } } } } } }, "responses": { "200": { "description": "DND updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Status message", "example": "DND status for extension 1010 set to true." }, "extension": { "type": "string", "description": "The extension number", "example": "1010" }, "dndStatus": { "type": "boolean", "description": "Updated DND state", "example": true } } } } } } } } }, "/extensions/me/endpoint": { "get": { "summary": "List registered endpoints", "description": "Returns all SIP endpoints/devices registered to the user's extension. Polled every 10 seconds on the dashboard.", "tags": [ "Extensions" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "List of registered devices", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/RegisteredDevice" } } } } } } } }, "/extensions/me/voicemails": { "get": { "summary": "List voicemails", "description": "Returns voicemail messages for the authenticated user.", "tags": [ "Voicemail" ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "List of voicemails", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Voicemail" } } } } } } } }, "/extensions/me/voicemails/{messageId}/download": { "get": { "summary": "Download voicemail audio", "description": "Downloads the WAV audio file for a specific voicemail.", "tags": [ "Voicemail" ], "security": [ { "BearerAuth": [] } ], "parameters": [ { "in": "path", "name": "messageId", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "WAV audio file", "content": { "audio/wav": { "schema": { "type": "string", "format": "binary" } } } } } } }, "/extensions/me/voicemails/{messageId}/move": { "patch": { "summary": "Move voicemail to folder", "description": "Moves a voicemail into a different folder for organization.", "tags": [ "Voicemail" ], "security": [ { "BearerAuth": [] } ], "parameters": [ { "in": "path", "name": "messageId", "required": true, "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "targetFolder" ], "properties": { "targetFolder": { "type": "string", "enum": [ "INBOX", "Family", "Friends", "Old", "Work", "Urgent" ] } } } } } }, "responses": { "200": { "description": "Voicemail moved", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Status message", "example": "Voicemail moved from Old to Friends." }, "messageId": { "type": "string", "description": "The voicemail message ID", "example": "849c9236" }, "sourceFolder": { "type": "string", "description": "Original folder", "example": "Old" }, "targetFolder": { "type": "string", "description": "Destination folder", "example": "Friends" }, "newMessageNumber": { "type": "string", "description": "New message number after move", "example": "msg0001" } } } } } } } } }, "/extensions/me/voicemails/{messageId}": { "delete": { "summary": "Delete voicemail", "description": "Permanently deletes a voicemail message.", "tags": [ "Voicemail" ], "security": [ { "BearerAuth": [] } ], "parameters": [ { "in": "path", "name": "messageId", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "Voicemail deleted", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string", "description": "Status message", "example": "Voicemail msg0033 deleted permanently from Old." }, "messageId": { "type": "string", "description": "The voicemail message ID", "example": "37aca380" }, "folder": { "type": "string", "description": "The folder the voicemail was in", "example": "Old" }, "originalMessageId": { "type": "string", "description": "The original message number", "example": "msg0033" } } } } } } } } }, "/conferences": { "get": { "summary": "List conference rooms", "description": "Returns all currently active conference rooms and their participant counts.", "tags": [ "Conferences" ], "responses": { "200": { "description": "List of conference rooms", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ConferenceRoom" } } } } } } } }, "/conferences/{conferenceId}": { "get": { "summary": "Get conference participants", "description": "Returns the list of participants currently in a specific conference room.", "tags": [ "Conferences" ], "parameters": [ { "in": "path", "name": "conferenceId", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "List of participants", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Participant" } } } } } } } }, "/conferences/{conferenceId}/connectme": { "post": { "summary": "Connect to conference", "description": "Dials the authenticated user's extension and bridges them into the specified conference room.", "tags": [ "Conferences" ], "parameters": [ { "in": "path", "name": "conferenceId", "required": true, "schema": { "type": "string" } } ], "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "Connected to conference" } } } }, "/system/records": { "get": { "summary": "Get call statistics", "description": "Returns aggregate call statistics for the LiteNet PBX. Public endpoint \u2014 no authentication required.", "tags": [ "System" ], "responses": { "200": { "description": "Call statistics", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CallRecords" } } } } } } }, "/system/survey": { "get": { "summary": "Get hardware survey data", "description": "Returns aggregated hardware survey data showing device types, brands, and devices needing categorization. Public endpoint \u2014 no authentication required.", "tags": [ "System" ], "responses": { "200": { "description": "Survey data", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SurveyData" } } } } } } } }, "components": { "securitySchemes": { "BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "UUID", "description": "Obtain a token via Discord OAuth at `/auth/discord`.\nPass it as `Authorization: Bearer *** schemas:\n" }, "ExtensionDetails": { "type": "object", "properties": { "extensionId": { "type": "string", "description": "The 4-digit extension number", "example": "1010" }, "user": { "type": "object", "description": "Discord user profile", "properties": { "id": { "type": "string", "description": "Discord user ID", "example": "123456789012345678" }, "name": { "type": "string", "description": "Discord display name", "example": "rocord" }, "avatar": { "type": "string", "description": "Discord avatar hash", "example": "a1b2c3d4e5f6" }, "voicemail": { "type": "string", "description": "Voicemail context", "example": "default" }, "extPassword": { "type": "string", "description": "SIP secret (masked in dashboard)" } } }, "coreDevice": { "type": "object", "description": "PBX device configuration", "properties": { "deviceid": { "type": "string", "example": "1010" }, "tech": { "type": "string", "example": "SIP" }, "dial": { "type": "string", "example": "SIP/1010" } } } } }, "ActiveCall": { "type": "object", "properties": { "uniqueId": { "type": "string", "description": "Unique call identifier" }, "caller": { "type": "object", "properties": { "name": { "type": "string" }, "number": { "type": "string" } } }, "connectedLine": { "type": "object", "properties": { "name": { "type": "string" }, "number": { "type": "string" } } }, "state": { "type": "string", "description": "Call state (e.g. \"Up\", \"Ring\")" }, "duration": { "type": "integer", "description": "Call duration in seconds" } } }, "RegisteredDevice": { "type": "object", "properties": { "uri": { "type": "string", "description": "SIP contact URI", "example": "sip:1010@192.168.1.100:5060" }, "useragent": { "type": "string", "description": "User-Agent header from the device", "example": "Linphone/4.4.0" }, "ip": { "type": "string", "description": "Client IP address", "example": "192.168.1.100" }, "port": { "type": "string", "description": "Client port", "example": "5060" }, "pingMs": { "type": "string", "description": "Round-trip latency in milliseconds", "example": "12.34" } } }, "Voicemail": { "type": "object", "properties": { "messageId": { "type": "string", "description": "Unique voicemail identifier" }, "callerIdNum": { "type": "string", "description": "Caller's phone number" }, "callerIdName": { "type": "string", "description": "Caller's name (if available)" }, "date": { "type": "string", "format": "date-time", "description": "Timestamp of the voicemail" }, "duration": { "type": "number", "description": "Duration in seconds" }, "fileSize": { "type": "integer", "description": "Audio file size in bytes" }, "hasAudio": { "type": "boolean", "description": "Whether audio is available for playback" }, "folder": { "type": "string", "enum": [ "INBOX", "Family", "Friends", "Old", "Work", "Urgent" ], "description": "Current folder" }, "originalMessageId": { "type": "string", "description": "Original message ID before any moves" } } }, "ConferenceRoom": { "type": "object", "properties": { "conferenceId": { "type": "string", "description": "Conference room identifier", "example": 2000 }, "parties": { "type": "integer", "description": "Number of participants", "example": 3 }, "locked": { "type": "boolean", "description": "Whether the room is locked" } } }, "Participant": { "type": "object", "properties": { "channel": { "type": "string", "description": "Asterisk channel identifier" }, "callerIdNum": { "type": "string", "description": "Participant's extension number" }, "callerIdName": { "type": "string", "description": "Participant's display name" }, "muted": { "type": "boolean", "description": "Whether the participant is muted" }, "admin": { "type": "boolean", "description": "Whether the participant is a conference admin" }, "talking": { "type": "boolean", "description": "Whether the participant is currently speaking" } } }, "CallRecords": { "type": "object", "properties": { "records": { "type": "object", "properties": { "total_calls_ever_placed": { "type": "integer", "description": "Total calls since launch", "example": 5324 }, "record_calls": { "type": "object", "description": "Single-day call record", "properties": { "count": { "type": "integer" }, "date": { "type": "string", "format": "date" } } }, "last_updated": { "type": "string", "format": "date-time" } }, "additionalProperties": { "type": "integer", "description": "Monthly call totals (e.g. monthly_total_2025-01)" } } } }, "SurveyData": { "type": "object", "properties": { "phoneTypes": { "type": "object", "description": "Device types and their counts", "additionalProperties": { "type": "integer" }, "example": { "softphone": 45, "ip_phone": 23, "ata": 8 } }, "brands": { "type": "object", "description": "Device brands and their counts", "additionalProperties": { "type": "integer" }, "example": { "Polycom": 12, "Cisco": 8, "Yealink": 7 } }, "needsCategorization": { "type": "array", "description": "Devices that couldn't be automatically categorized", "items": { "type": "object", "properties": { "ua": { "type": "string", "description": "User-Agent string" } } } }, "lastUpdated": { "type": "string", "format": "date-time", "description": "When the survey data was last refreshed" } } } }, "schemas": { "ExtensionDetails": { "type": "object", "properties": { "status": { "type": "boolean", "description": "Whether the request was successful", "example": true }, "message": { "type": "string", "description": "Status message", "example": "Extension found successfully" }, "id": { "type": "string", "description": "Base64-encoded extension identifier", "example": "ZXh0ZW5zaW9uOjEwMTA=" }, "extensionId": { "type": "string", "description": "The 4-digit extension number", "example": "1010" }, "user": { "type": "object", "description": "User profile and PBX settings", "properties": { "name": { "type": "string", "description": "Discord display name", "example": "rocord" }, "outboundCid": { "type": "string", "description": "Outbound caller ID override", "example": "" }, "voicemail": { "type": "string", "description": "Voicemail context", "example": "default" }, "ringtimer": { "type": "integer", "description": "Ring time in seconds before voicemail", "example": 0 }, "noanswer": { "type": "string", "description": "No-answer destination", "example": "" }, "noanswerDestination": { "type": "string", "description": "No-answer destination context", "example": "" }, "noanswerCid": { "type": "string", "description": "Caller ID on no-answer", "example": "" }, "busyCid": { "type": "string", "description": "Caller ID on busy", "example": "" }, "sipname": { "type": "string", "description": "SIP display name", "example": "" }, "extPassword": { "type": "string", "description": "SIP secret (masked in dashboard)", "example": "REDACTED" } } }, "coreDevice": { "type": "object", "description": "PBX device configuration", "properties": { "deviceId": { "type": "string", "description": "Device identifier", "example": "1010" }, "dial": { "type": "string", "description": "Asterisk dial string", "example": "PJSIP/1010" }, "devicetype": { "type": "string", "description": "Device type (fixed, adhoc, etc.)", "example": "fixed" }, "description": { "type": "string", "description": "Human-readable device description", "example": "rocord" }, "emergencyCid": { "type": "string", "description": "Emergency caller ID override", "example": "" }, "tech": { "type": "string", "description": "SIP technology driver", "example": "pjsip" } } } } }, "ActiveCall": { "type": "object", "properties": { "channel": { "type": "string", "description": "Asterisk channel identifier", "example": "PJSIP/1010-00000002" }, "uniqueId": { "type": "string", "description": "Unique call identifier", "example": "1781687772.6" }, "caller": { "type": "object", "properties": { "number": { "type": "string", "description": "Caller number", "example": "1010" }, "name": { "type": "string", "description": "Caller display name", "example": "Call Me Test (MusicOnHold)" } } }, "connectedLine": { "type": "object", "properties": { "number": { "type": "string", "description": "Connected line number", "example": "1010" }, "name": { "type": "string", "description": "Connected line display name", "example": "Call Me Test (MusicOnHold)" } } }, "state": { "type": "string", "description": "Call state (e.g. \"Up\", \"Ring\")", "example": "Up" }, "duration": { "type": "string", "description": "Call duration in HH:MM:SS format", "example": "00:01:49" }, "application": { "type": "string", "description": "Asterisk application name", "example": "MusicOnHold" }, "applicationData": { "type": "string", "description": "Application data/arguments", "example": "" } } }, "RegisteredDevice": { "type": "object", "properties": { "uri": { "type": "string", "description": "SIP contact URI", "example": "sip:1010@192.168.1.100:5060" }, "useragent": { "type": "string", "description": "User-Agent header from the device", "example": "Linphone/4.4.0" }, "ip": { "type": "string", "description": "Client IP address", "example": "192.168.1.100" }, "port": { "type": "string", "description": "Client port", "example": "5060" }, "pingMs": { "type": "string", "description": "Round-trip latency in milliseconds", "example": "12.34" } } }, "Voicemail": { "type": "object", "properties": { "messageId": { "type": "string", "description": "Unique voicemail identifier" }, "callerIdNum": { "type": "string", "description": "Caller's phone number" }, "callerIdName": { "type": "string", "description": "Caller's name (if available)" }, "date": { "type": "string", "description": "Timestamp of the voicemail", "example": "Wed Mar 18 11:57:09 PM UTC 2026" }, "duration": { "type": "number", "description": "Duration in seconds" }, "fileSize": { "type": "integer", "description": "Audio file size in bytes" }, "hasAudio": { "type": "boolean", "description": "Whether audio is available for playback" }, "folder": { "type": "string", "enum": [ "INBOX", "Family", "Friends", "Old", "Work", "Urgent" ], "description": "Current folder" }, "originalMessageId": { "type": "string", "description": "Original message ID before any moves" } } }, "ConferenceRoom": { "type": "object", "properties": { "conferenceId": { "type": "string", "description": "Conference room identifier", "example": "400" }, "parties": { "type": "integer", "description": "Number of participants", "example": 1 }, "marked": { "type": "integer", "description": "Number of marked participants", "example": 0 }, "locked": { "type": "boolean", "description": "Whether the room is locked", "example": false } } }, "Participant": { "type": "object", "properties": { "channel": { "type": "string", "description": "Asterisk channel identifier" }, "callerIdNum": { "type": "string", "description": "Participant's extension number" }, "callerIdName": { "type": "string", "description": "Participant's display name" }, "muted": { "type": "boolean", "description": "Whether the participant is muted" }, "admin": { "type": "boolean", "description": "Whether the participant is a conference admin" }, "talking": { "type": "boolean", "description": "Whether the participant is currently speaking" } } }, "CallRecords": { "type": "object", "properties": { "records": { "type": "object", "properties": { "total_calls_ever_placed": { "type": "integer", "description": "Total calls since launch", "example": 5324 }, "record_calls": { "type": "object", "description": "Single-day call record", "properties": { "count": { "type": "integer" }, "date": { "type": "string", "format": "date" } } }, "last_updated": { "type": "string", "format": "date-time" } }, "additionalProperties": { "type": "integer", "description": "Monthly call totals (e.g. monthly_total_2025-01)" } } } }, "SurveyData": { "type": "object", "properties": { "phoneTypes": { "type": "object", "description": "Device types and their counts", "additionalProperties": { "type": "integer" }, "example": { "softphone": 45, "ip_phone": 23, "ata": 8 } }, "brands": { "type": "object", "description": "Device brands and their counts", "additionalProperties": { "type": "integer" }, "example": { "Polycom": 12, "Cisco": 8, "Yealink": 7 } }, "needsCategorization": { "type": "array", "description": "Devices that couldn't be automatically categorized", "items": { "type": "object", "properties": { "ua": { "type": "string", "description": "User-Agent string" } } } }, "lastUpdated": { "type": "string", "format": "date-time", "description": "When the survey data was last refreshed" } } } } } }