Complete HTTP and WebSocket API documentation for integrating with IP Camera.
Pro Feature: Direct API access (curl, scripts, Home Assistant) requires a Pro license. The web dashboard is available to all users.
The IP Camera API provides HTTP endpoints and WebSocket communication for controlling camera settings, accessing video streams, and integrating with external systems like Home Assistant.
All API requests are made to the device's IP address on port 8443 (HTTPS):
https://<device-ip>:8443
| Access Method | Free Users | Pro Users |
|---|---|---|
| Web Dashboard (browser) | Basic features only | All features |
| Direct API (curl, scripts, Home Assistant) | Blocked (403) | Full access |
curl -k https://192.168.1.100:8443/status
Note: The -k flag accepts the self-signed certificate. For production, install the certificate from /cert.
When password protection is enabled, most endpoints require authentication.
After authenticating via POST /auth, include the token in requests:
Authorization: Bearer <token>
Authenticate and receive a session token.
curl -k -X POST https://192.168.1.100:8443/auth \
-H "Content-Type: application/json" \
-d '{"password": "your_password"}'
{
"success": true,
"token": "a1b2c3d4e5f6...",
"csrfToken": "g7h8i9j0k1l2..."
}
{
"success": false,
"error": "Invalid password"
}
{
"success": false,
"error": "Too many attempts",
"lockout": true,
"lockoutRemaining": 30
}
Check if authentication is enabled.
{
"enabled": true,
"configured": true
}
Revoke the current session token.
{
"success": true
}
/ and dashboard assets/auth, /auth/status, /auth/logout/cert/infoDownload the self-signed certificate (PEM format) for installing on client devices.
Get certificate metadata.
{
"subject": "CN=IP Camera, O=Local Network, C=US",
"issuer": "CN=IP Camera, O=Local Network, C=US",
"notBefore": 1707000000000,
"notAfter": 1738536000000,
"serialNumber": "a1b2c3d4e5f6",
"status": "valid",
"downloadUrl": "/cert"
}
Note: notBefore and notAfter are Unix timestamps in milliseconds.
Regenerate the HTTPS certificate. Useful after IP address change. Requires authentication.
curl -k -X POST -H "Authorization: Bearer YOUR_TOKEN" \ https://192.168.1.100:8443/cert/regenerate
{
"success": true
}
State-changing requests (POST, PUT, DELETE) require CSRF protection when using cookie-based authentication.
CSRF validation applies to requests that:
POST, PUT, DELETE)Note: Pro users using Bearer token authentication (via Authorization header) are NOT subject to CSRF checks. CSRF protection only applies to cookie-based authentication.
When authenticating via POST /auth, the response includes a csrfToken field:
{
"success": true,
"token": "a1b2c3d4e5f6...",
"csrfToken": "g7h8i9j0k1l2..."
}
Include the CSRF token in the X-CSRF-Token header for all state-changing requests:
X-CSRF-Token: g7h8i9j0k1l2...
curl -X POST https://192.168.1.100:8443/settings \
-H "Cookie: session=..." \
-H "X-CSRF-Token: your_csrf_token" \
-H "Content-Type: application/json" \
-d '{"frameRate": 30}'
If the CSRF token is missing or invalid, the server returns a 403 Forbidden response:
{
"error": "Invalid CSRF token"
}
All API endpoints require HTTPS (port 8443). The dashboard requires HTTPS for secure session cookies.
An HTTP listener on port 8080 provides friendly handling for users who type http://:
| Route Type | HTTP Behavior |
|---|---|
Dashboard/UI (/, *.html, *.js, *.css) |
302 Redirect to https://host:8443/... |
Session endpoints (/auth, /auth/logout) |
403 Forbidden with JSON error |
| API endpoints | 403 Forbidden with JSON error |
| WebSocket upgrade | 403 Forbidden (cannot redirect WebSocket) |
When HTTPS is required but the request was made over HTTP, the server returns:
{
"error": "HTTPS required",
"httpsPort": 8443
}
Note: Always use https:// with port 8443 for API requests. The HTTP server on port 8080 exists only to redirect users who accidentally use http://.
For deployments behind a TLS-terminating proxy (nginx, Apache, Caddy, Cloudflare), the app supports the X-Forwarded-Proto header.
X-Forwarded-Proto: https header in proxy configlocation /ipcamera/ {
proxy_pass https://192.168.1.100:8443/;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_ssl_verify off;
}
Security Warning: Only enable reverse proxy mode if you trust the X-Forwarded-Proto header. When enabled, the header is trusted from any source. Ensure your network prevents unauthorized clients from connecting directly to the app, bypassing the proxy.
Note: Reverse proxy mode is a PRO feature and must be enabled in app settings before the X-Forwarded-Proto header will be recognized.
MJPEG video stream for viewing in browsers and media players.
<img src="https://192.168.1.100:8443/stream?token=YOUR_TOKEN" />
Latest JPEG frame from the video stream.
curl -k "https://192.168.1.100:8443/snapshot?token=YOUR_TOKEN" -o snapshot.jpg
High-resolution still capture (full sensor resolution). Must be triggered via WebSocket first.
Get all current settings.
curl -k -H "Authorization: Bearer YOUR_TOKEN" https://192.168.1.100:8443/settings
{
"resolution": "1280x720",
"frameRate": 30,
"jpegQuality": 85,
"cameraId": "0",
"torchEnabled": false,
"audioEnabled": true,
"rotation": 0,
"keepScreenOn": true,
"showPreview": true,
"motionEnabled": true,
"motionSensitivity": 5,
"soundEnabled": false,
"rtspEnabled": false,
"mqttEnabled": false,
"license": {
"isPro": true,
"state": "ACTIVE"
}
}
Update settings. Partial updates allowed.
curl -k -X POST https://192.168.1.100:8443/settings \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resolution": "1920x1080", "frameRate": 20}'
| Key | Type | Description |
|---|---|---|
| Camera Settings | ||
resolution | string | Video resolution (e.g., "1280x720") |
frameRate | int | Frames per second (1-60) |
jpegQuality | int | JPEG quality for MJPEG (1-100) |
cameraId | string | Camera ID ("0" = back, "1" = front) |
useFrontCamera | boolean | Use front camera |
torchEnabled | boolean | Flashlight on/off |
rotation | int | Manual rotation (0, 90, 180, 270) |
| Display Settings | ||
keepScreenOn | boolean | Keep screen on while streaming |
showPreview | boolean | Show camera preview on device |
| Background Operation | ||
runInBackground | boolean | Allow background operation |
cameraStandbyMode | boolean | Enter standby when no clients |
| Audio Settings | ||
audioEnabled | boolean | Enable audio capture |
| Motion Detection | ||
motionEnabled | boolean | Enable motion detection |
motionSensitivity | int | Motion sensitivity (1-10) |
motionCooldown | int | Cooldown between events (seconds) |
| Sound Detection | ||
soundEnabled | boolean | Enable sound detection |
soundThreshold | int | Sound threshold (0-100) |
soundCooldown | int | Cooldown between events (seconds) |
| ML Classification | ||
dogBarkClassificationEnabled | boolean | Enable dog bark detection |
dogBarkClassificationConfidence | int | Confidence threshold (1-100) |
babyCryClassificationEnabled | boolean | Enable baby cry detection |
babyCryClassificationConfidence | int | Confidence threshold (1-100) |
objectPersonDetectionEnabled | boolean | Enable person detection |
objectPersonDetectionConfidence | int | Confidence threshold (1-100) |
objectDogDetectionEnabled | boolean | Enable dog object detection |
objectDogDetectionConfidence | int | Confidence threshold (1-100) |
objectDetectionSamplingRate | int | Sampling rate for object detection |
| Event History | ||
eventHistoryEnabled | boolean | Enable event history |
| RTSP Settings | ||
rtspEnabled | boolean | Enable RTSP server |
rtspPort | int | RTSP port number |
rtspPath | string | Stream path (e.g., "/stream") |
rtspUsername | string | RTSP authentication username |
rtspHasPassword | boolean | Whether password is set (read-only) |
| MQTT Settings | ||
mqttEnabled | boolean | Enable MQTT client |
mqttBrokerUrl | string | Broker URL |
mqttPort | int | Broker port |
mqttHasUsername | boolean | Whether username is set (read-only) |
mqttHasPassword | boolean | Whether password is set (read-only) |
mqttClientId | string | Client ID |
mqttTopicPrefix | string | Topic prefix |
mqttUseTls | boolean | Use TLS encryption |
mqttAcceptSelfSigned | boolean | Accept self-signed certificates |
mqttTelemetryIntervalSec | int | Telemetry interval (seconds) |
mqttCommandsEnabled | boolean | Enable MQTT commands |
The license field is a nested object that provides Pro license status information:
{
"license": {
"isPro": true,
"state": "ACTIVE",
"source": "REAL_PURCHASE",
"billing": {
"available": true,
"status": "CONNECTED"
}
}
}
| Field | Type | Description |
|---|---|---|
license.isPro | boolean | Whether Pro license is active |
license.state | string | "ACTIVE", "INACTIVE", or "UNKNOWN" |
license.source | string | "REAL_PURCHASE", "DEBUG_OVERRIDE", or "NONE" |
license.billing.available | boolean | Whether billing service is available |
license.billing.status | string | "CONNECTED", "UNAVAILABLE_RECOVERABLE", or "UNAVAILABLE_HARD" |
Note: Fields marked (read-only) are returned by GET /settings but cannot be modified via POST /settings. Use dedicated endpoints (e.g., /api/rtsp/apply-settings, /api/mqtt/apply-settings) to update credentials.
Current server and streaming status.
{
"clients": 2,
"wsClients": 1,
"streaming": true,
"cameraRunning": true,
"settings": { ... }
}
Camera hardware capabilities.
{
"cameraIds": ["0", "1"],
"resolutions": ["1280x720", "1920x1080"],
"frameRates": [15, 20, 30, 60],
"maxFrameRate": 60
}
Toggle the device flashlight/torch.
curl -k -X POST -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/torch"
{
"torchEnabled": true
}
H.264 video streaming compatible with VLC, ffmpeg, and security camera software.
Connection Limits:
RTSP server status.
{
"enabled": true,
"running": true,
"port": 8554,
"path": "/stream",
"clients": 2
}
Start RTSP server.
Stop RTSP server.
Restart RTSP server with current settings.
Update RTSP configuration.
{
"rtspPort": 8554,
"rtspPath": "/stream",
"rtspUsername": "admin",
"rtspPassword": "secret"
}
Apply new RTSP settings atomically and restart the server.
{
"rtspPort": 8554,
"rtspPath": "/stream",
"rtspUsername": "admin",
"rtspPassword": "secret"
}
{
"success": true
}
ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:8554/stream -f null -
vlc rtsp://192.168.1.100:8554/stream
Integrate with Home Assistant, Node-RED, and other MQTT-based automation systems.
MQTT client connection status.
{
"enabled": true,
"connected": true,
"brokerUrl": "192.168.1.100",
"port": 1883,
"topicPrefix": "ipcamera"
}
Get current MQTT settings (passwords redacted).
Update MQTT configuration.
{
"mqttEnabled": true,
"mqttBrokerUrl": "192.168.1.100",
"mqttPort": 1883,
"mqttTopicPrefix": "ipcamera"
}
Test MQTT broker connection.
Apply MQTT settings with password verification. Requires the current password when modifying credentials.
{
"currentPassword": "existing_password",
"settings": {
"mqttEnabled": true,
"mqttBrokerUrl": "192.168.1.100",
"mqttPort": 1883,
"mqttUsername": "newuser",
"mqttPassword": "newpass",
"mqttClientId": "ipcamera-001",
"mqttTopicPrefix": "ipcamera",
"mqttUseTls": false,
"mqttAcceptSelfSigned": false,
"mqttTelemetryIntervalSec": 60,
"mqttCommandsEnabled": false
}
}
Note: currentPassword is only required when changing credentials (username, password) or disabling authentication. For non-credential settings, it can be omitted. First-time credential setup does not require verification.
{
"success": true
}
{
"error": "Current password required for credential changes"
}
Query detection events.
| Parameter | Type | Description |
|---|---|---|
limit | int | Max events (1-10000, default: 1000) |
since | long | Timestamp in ms (0 = start of today) |
type | string | MOTION, ANY_SOUND, DOG_BARK, etc. |
bucketMs | long | Aggregate events into time buckets (60000-3600000 ms) |
curl -k -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/events?since=0&type=MOTION"
{
"serverNow": 1234567890000,
"dayStart": 1234483200000,
"events": [
{
"id": 1,
"eventId": 1001,
"timestamp": 1234567890000,
"type": "MOTION",
"changedPercent": 12.5,
"width": 1280,
"height": 720
},
{
"id": 2,
"eventId": 1002,
"timestamp": 1234567891000,
"type": "ANY_SOUND",
"db": -25.5,
"rms": 0.45
},
{
"id": 3,
"eventId": 1003,
"timestamp": 1234567892000,
"type": "DOG_BARK",
"className": "Dog",
"confidence": 92
},
{
"id": 4,
"eventId": 1004,
"timestamp": 1234567893000,
"type": "OBJECT_PERSON",
"objectClass": "person",
"confidence": 85,
"eventType": "appeared"
}
],
"summary": [
{ "type": "MOTION", "count": 5, "lastTimestamp": 1234567890000 },
{ "type": "ANY_SOUND", "count": 3, "lastTimestamp": 1234567891000 },
{ "type": "DOG_BARK", "count": 2, "lastTimestamp": 1234567892000 },
{ "type": "OBJECT_PERSON", "count": 1, "lastTimestamp": 1234567893000 }
]
}
When bucketMs is provided, the response format changes from individual events to aggregated buckets:
{
"buckets": [
{
"timestamp": 1699200000000,
"counts": {
"MOTION": 5,
"ANY_SOUND": 3,
"DOG_BARK": 1
}
},
{
"timestamp": 1699200060000,
"counts": {
"MOTION": 2
}
}
],
"bucketMs": 60000,
"timeRange": {
"start": 1699200000000,
"end": 1699203600000
}
}
Tip: Use bucketed queries for time-series analytics and event frequency charts.
Get time range of stored events.
curl -k -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/events/range"
{
"minTimestamp": 1234567000000,
"maxTimestamp": 1234567890000,
"totalEvents": 1523
}
Delete all stored events.
| Parameter | Type | Description |
|---|---|---|
confirm | string | Must be true (required for safety) |
curl -k -X POST -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/events/clear?confirm=true"
{
"success": true,
"cleared": 1523
}
Get storage usage statistics for event history.
curl -k -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/api/storage/stats"
{
"databaseSize": "2.5 MB",
"databaseSizeBytes": 2621440,
"totalEvents": 1990,
"motionEvents": 1200,
"soundEvents": 328,
"eventsByType": {
"MOTION": 1200,
"ANY_SOUND": 300,
"DOG_BARK": 23,
"BABY_CRY": 5,
"OBJECT_PERSON": 450,
"OBJECT_DOG": 12
},
"minTimestamp": 1234567000000,
"maxTimestamp": 1234567890000,
"deviceStorageTotal": "64.0 GB",
"deviceStorageAvailable": "32.5 GB",
"deviceStorageTotalBytes": 68719476736,
"deviceStorageAvailableBytes": 34896609280
}
Export all events as CSV. PRO
curl -k -H "Authorization: Bearer YOUR_TOKEN" \ "https://192.168.1.100:8443/api/events/export" \ -o ip-camera-events.csv
Response: CSV file with columns: id, type, timestamp, confidence, details, cameraId, resolution, frameRate, lightLevel, motionZones, thumbnailPath, metadata
| Status | Body | Cause |
|---|---|---|
| 403 | {"error":"Pro license required","feature":"event_export"} | Pro license not active |
| 500 | Event history unavailable | Database not initialized |
Real-time communication for live updates and control.
wss://192.168.1.100:8443/ws?token=YOUR_TOKEN
Upon successful WebSocket connection, the server sends a connected message:
{"type": "connected", "authenticated": true, "timestamp": 1234567890000}
Immediately after authentication, the server automatically sends a full state snapshot so the client has everything it needs without additional requests:
status — streaming state, detection state, and current settingssystem_info — CPU, memory, battery, and stream statisticsmqtt_status — MQTT connection state (enabled, connected, broker info)rtsp_status — RTSP server state (enabled, running, client count)If authentication is required but no valid token was provided, the server sends:
{"type": "auth_required", "timestamp": 1234567890000}
The client must respond with an auth message within 10 seconds.
| Type | Description |
|---|---|
auth | WebSocket authentication with token |
ping | Keepalive (server responds with pong) |
setting | Update a single setting |
settings_batch | Update multiple settings |
capture | Trigger high-res capture |
enableH264 | Enable H.264 stream |
requestKeyframe | Request H.264 keyframe |
h264_quality | Adjust H.264 encoding quality (0-100) |
stream_control | Start/stop streaming |
audio_subscribe | Subscribe to audio stream (Two-Way Audio) |
audio | Send audio data to device (Two-Way Audio) |
tts | Text-to-speech on device (Two-Way Audio) |
| Type | Description |
|---|---|
connected | Initial connection confirmation |
auth_required | Authentication needed prompt |
auth | Authentication success/failure response |
error | Error message with code and details |
pong | Response to ping keepalive |
settings | Settings changed (broadcast) |
setting_ack | Single setting update acknowledgment |
settings_batch_ack | Batch settings update acknowledgment |
status | Streaming status update |
system_info | Device info (CPU, memory, battery) |
h264_ack | H.264 enable acknowledgment |
motion_detected | Motion event |
sound_detected | Sound event |
sound_classified | Dog bark classified |
baby_cry_classified | Baby cry classified |
object_detected | Person/dog detected |
detection_frame | All tracked objects in frame |
capture_ready | High-res capture available |
capture_busy | Capture already in progress |
mqtt_status | MQTT connection state |
rtsp_status | RTSP server state |
license:changed | Pro license status change |
capabilitiesChanged | Camera capabilities changed |
audio_ack | Audio subscribe acknowledgment |
audio | Audio data from device (Two-Way Audio) |
{"type": "auth", "token": "your_auth_token"}
{"type": "setting", "key": "resolution", "value": "1920x1080"}
{"type": "error", "message": "Authentication required"}
| Status | Meaning |
|---|---|
| 400 | Invalid request (bad JSON, missing fields) |
| 401 | Authentication required or invalid token |
| 403 | Forbidden (Pro required, HTTPS required) |
| 429 | Rate limit exceeded |
| 500 | Server error |
| 503 | Service unavailable (camera not started) |
{"error": "Description of the error"}
{
"error": "Pro license required",
"feature": "rtsp_streaming",
"hint": "Access this feature through the web dashboard or upgrade to Pro"
}
The feature field identifies which Pro feature was requested:
| Feature ID | Endpoints/Features |
|---|---|
rtsp_streaming | /api/rtsp/* endpoints |
mqtt_integration | /api/mqtt/* endpoints |
event_history | /events, /events/range, /events/clear |
event_export | /api/events/export |
storage_analytics | /api/storage/stats |
certificate_download | /cert |
{
"success": false,
"errors": [
"unknownKey: Unknown setting",
"frameRate: Value must be between 1 and 60"
]
}
The errors array lists all validation failures. Each entry follows the format key: message.
{
"success": false,
"error": "Too many attempts",
"lockout": true,
"lockoutRemaining": 30
}
After 5 failed login attempts, the account is locked for 30 seconds. The lockoutRemaining field shows seconds until retry is allowed.
Download the self-signed certificate to eliminate browser warnings:
curl -k https://192.168.1.100:8443/cert -o ipcamera.pem