Skip to content

API Overview

The Flex Video REST API provides programmatic control over video pipelines, cameras, and system configuration.

Base URL

https://<encoder-ip>:3539

Replace <encoder-ip> with your encoder's IP address.

Self-Signed Certificate

The API is served over HTTPS using a self-signed certificate generated during installation. When using curl, add the -k flag to skip certificate verification. For production integrations, you can import the certificate from /opt/flex/certs/ into your trust store.

Web UI Proxy

The web interface (port 8443) includes a built-in reverse proxy to the API at /api/. Third-party integrations should use the direct API URL on port 3539.

Interactive Documentation (Optional)

Swagger UI provides interactive API exploration. It is included in some installer configurations.

  • URL: http://<encoder-ip>:38081 (Swagger UI itself uses HTTP)

If installed, Swagger UI allows you to:

  • Browse all endpoints
  • View request/response schemas
  • Try API calls directly

Self-Signed Certificate

Before using "Try it out" in Swagger UI, you must first visit https://<encoder-ip>:3539 in your browser and accept the self-signed certificate. Otherwise, API requests from Swagger UI will silently fail with a network error.

Authentication

Authentication is optional. When enabled:

Session Token

Obtain a token via login:

curl -k -X POST https://<encoder-ip>:3539/flex/auth/login \
  -H "Content-Type: application/json" \
  -d '{"password": "your-password"}'

Use the token in subsequent requests:

curl -k -H "Authorization: Bearer <token>" https://<encoder-ip>:3539/flex/pipeline

Endpoints Overview

Health & Version

Method Endpoint Description
GET /flex/health Health check
GET /flex/healthz Kubernetes health check
GET /flex/version Version information

Pipelines

Method Endpoint Description
GET /flex/pipeline List pipelines
POST /flex/pipeline Create pipeline
GET /flex/pipeline/{id} Get pipeline
PUT /flex/pipeline/{id} Update pipeline
DELETE /flex/pipeline/{id} Delete pipeline
PUT /flex/pipeline/{id}/play Start pipeline
PUT /flex/pipeline/{id}/stop Stop pipeline
GET /flex/pipeline/{id}/status Get status

Cameras

Method Endpoint Description
GET /flex/cameras List cameras
GET /flex/camera?path= Get camera capabilities
GET /flex/cameras/events SSE camera events

Settings

Method Endpoint Description
GET /flex/settings Get settings
PUT /flex/settings Update settings

Files

Method Endpoint Description
GET /flex/files/framegrabs List framegrabs
GET /flex/files/framegrabs/{file} Download framegrab
DELETE /flex/files/framegrabs/{file} Delete framegrab

Audio

Method Endpoint Description
GET /flex/audio-devices List ALSA audio capture devices

Webhooks

Method Endpoint Description
POST /flex/webhooks Register webhook
GET /flex/webhooks List webhooks
DELETE /flex/webhooks/{id} Unregister webhook

Response Format

Success Responses

{
  "id": "camera-1",
  "mode": "simple",
  "state": "playing",
  ...
}

Error Responses

{
  "message": "Human-readable error description",
  "code": "MACHINE_READABLE_CODE"
}

Common Error Codes

Code HTTP Status Description
VALIDATION_ERROR 400 Invalid request data
UNAUTHORIZED 401 Authentication required
LICENSE_ERROR 402 License required
NOT_FOUND 404 Resource not found
CONFLICT 409 Resource conflict
GSTREAMER_ERROR 500 Pipeline error
GSTREAMER_UNAVAILABLE 503 Backend unavailable
UNSUPPORTED_MEDIA_TYPE 415 Invalid Content-Type
RATE_LIMITED 429 Too many requests
PIPELINE_START_TIMEOUT 504 Pipeline didn't start

Server-Sent Events (SSE)

Real-time updates are available via SSE:

Pipeline Status Events

curl -k -N https://<encoder-ip>:3539/flex/pipeline/camera-1/status/events

Events:

event: pipeline_status
data: {"id":"camera-1","state":"playing",...}

event: pipeline_error
data: {"message":"Connection lost"}

Camera Events

curl -k -N https://<encoder-ip>:3539/flex/cameras/events

Events:

event: camera_added
data: {"device_path":"/dev/video0","device_name":"Webcam"}

event: camera_removed
data: {"device_path":"/dev/video0"}

Rate Limits

Endpoint Limit
POST /flex/auth/login 5 per 15 minutes per IP
DELETE /flex/files/framegrabs/{file} 60/min
DELETE /flex/files/framegrabs?pipeline_id= 10/min

Rate-limited responses return 429 Too Many Requests with a Retry-After header.

SDKs & Client Libraries

cURL Examples

Throughout this documentation, examples use cURL. Convert to your language:

import requests

response = requests.get('https://<encoder-ip>:3539/flex/pipeline', verify=False)
pipelines = response.json()
const response = await fetch('https://<encoder-ip>:3539/flex/pipeline');
const pipelines = await response.json();
import "crypto/tls"

client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    },
}
resp, err := client.Get("https://<encoder-ip>:3539/flex/pipeline")
// Handle response

Next Steps