Skip to content

How to call API methods in Astra?

Astra is controlled over an HTTP API served by the control server, the same listener that serves the web interface. Every method is public: the built-in web interface uses nothing else, so any client, script or AI coding agent may build its own interface on top of the same requests. All replies are JSON.

There are two ways to address a method. Both are served by the same control server and share the same authentication and roles.

Command entry point: POST {control_path}control/ with the command name in the cmd field of the JSON body:

{
"cmd": "toggle-user",
"id": "login"
}

Only POST is accepted here; any other method is answered 405.

Path entry point: {control_path}api/<cmd>[/{id}], addressed by the HTTP method and the path. The first path segment is the command, the optional second segment is the identifier of the addressed object (URI-encoded):

GET /api/stream-info/a001

A GET method has no body; a POST or PATCH method takes a JSON body.

Every method page in this section names the entry points that serve the method. Some methods are served on both entry points, some on one of them only. Both entry points are supported and neither is deprecated; new methods are added to the command entry point.

{control_path} is / by default. The control_path setting (Settings, settings.control_path in the configuration) inserts a prefix: with control_path set to ctl the entry points become /ctl/control/ and /ctl/api/<cmd>.

The control server port comes from the -p PORT command line option or the control_port setting. PORT is a port number or address:port.

Every request to both entry points is authenticated first. The credentials are tried in a fixed order; the first one that succeeds wins:

  1. The astra_session cookie: a session id issued by login.
  2. The Authorization: Basic <base64(login:password)> header, checked against the users table (see Users API).
  3. The Authorization: Bearer <session id> header: the same session id as in the cookie.

The Basic and Bearer prefixes are case-sensitive. A stale or unknown session id is skipped silently and the next credential is tried.

Password checks are rate-limited per client IP address: after 5 failed password checks within 60 seconds every further password check from that address is answered 429 until 60 seconds pass since the last failure. Session ids are not rate-limited. The client address is the peer address, or the X-Real-IP header when the HTTP authentication option x_real_ip or the allow_real_ip setting is enabled.

A rejected login or password (unknown user, wrong password, disabled user) writes [main] Authentication failed. Login:<login> IP:<address> to the log. A user of type 3 with a correct password is rejected without a log line.

The user type in the users table defines what the authenticated user may call:

  • 1 - control: full access, every method.
  • 2 - observer: read-only subset. An observer calling a method that is not in the observer subset receives 404, the same reply as for an unknown command.
  • 3 - a streaming user without access to the API: the credentials are rejected with 403.

Each method page states whether observers may call the method. The observer subset differs between the entry points for some methods, so the page names the role per entry point.

A successful call is answered 200 with Content-Type: application/json. Commands on the /control/ entry point that modify the configuration answer with the command name as the key:

{ "toggle-user": "ok" }

Error replies:

  • 400 - the body of a POST on the path entry point is not valid JSON, or a handler rejected the request: a required field is missing or a value is invalid. The body is empty.
  • 403 - no credentials, wrong credentials, a disabled user or a user of type 3. The body is empty.
  • 404 - unknown command, or an observer calling a control-only method. The body is empty.
  • 405 - the /control/ entry point called with a method other than POST. The body is empty.
  • 413 - the request body is larger than 16 MiB. The body is the HTML error page (Content-Type: text/html).
  • 429 - too many failed password checks from this address (see Authentication). The body is empty.

Every reply, success or error, carries Access-Control-Allow-Origin: *. An OPTIONS preflight on any API path is answered 200 with Access-Control-Allow-Methods: GET, POST and Access-Control-Allow-Headers: Content-Type, Authorization, so a web interface hosted on another origin may call the API directly from the browser.

With the api_access option enabled in the log settings (log.api_access in the configuration, set with the set-log command) most commands write a line to the log with the authenticated login, the client address and the action, for example:

[API] login:admin addr:192.168.1.10 toggle user id:login

Each command writes its own line. The methods of the Authentication API and version, sessions and log write none.

You may use curl in the console to call an API method. For example, you can obtain the Astra version:

Terminal window
curl \
--user login:password \
http://server:8000/api/version
  • login:password - login and password of a user with type 1 or 2
  • server:8000 - server address and control port
  • /api/version - path to API method

Reply:

{ "version": "Astra 260918 (commit:c109858f)" }

POST methods are used to modify the Astra configuration. For example, you may toggle a user from the console:

Terminal window
curl \
-X POST \
--user login:password \
-d '{"cmd":"toggle-user","id":"login"}' \
http://server:8000/control/
  • login:password - login and password of a user with type 1
  • -d '{...}' - request content in JSON format
  • server:8000 - server address and control port

Another way to execute curl, with the request body passed on the standard input:

Terminal window
curl -X POST --user login -d @- http://server:8000/control/ <<END
{
"cmd": "toggle-user",
"id": "login"
}
END

Without a password after the login, curl asks for the password.

On success Astra returns:

{ "toggle-user": "ok" }

You may use any programming language to control Astra. For example, a simple PHP script to toggle a user:

<?php
$req = json_encode(array(
'cmd' => 'toggle-user',
'id' => 'login',
));
$ch = curl_init("http://server:8000/control/");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, "login:password");
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
$reply = json_decode($res, true);

$reply['toggle-user'] is "ok" on success.

Every method of the API, with the entry points that serve it and the roles that may call it. {id} and {name} are the identifier of the addressed object in the path; on the command entry point the command name goes into the cmd field of the body.

CommandEntry pointsRoleSection
loginPOST /control/none, the body is the credentialLogin
logoutPOST /control/control, observerLogout
whoamiPOST /control/control, observerWho am I
ws-tokenPOST /control/control, observerWebSocket token
get-streamPOST /control/control, observerGet stream configuration
stream-infoGET /api/stream-info[/{id}]controlGet stream info
set-streamPOST /control/controlCreate or update stream, Delete stream
toggle-streamPOST /control/controlToggle stream
restart-streamPOST /control/controlRestart stream
check-streamPOST /control/control, observerCheck stream
stream-statusGET /api/stream-status/{id}controlGet stream status
set-stream-inputPOST /control/controlSwitch active input
set-stream-imagePOST /control/controlSet stream image
output-groupPOST /api/output-group[/{name}]controlOutput group
set-categoryPOST /control/controlSet category
get-adapterPOST /control/control, observerGet adapter configuration
adapter-infoGET /api/adapter-info[/{id}]controlGet adapter info
set-adapterPOST /control/controlCreate or update adapter, Delete adapter
toggle-adapterPOST /control/controlToggle adapter
restart-adapterPOST /control/controlRestart adapter
check-adapterPOST /control/control, observerCheck adapter
adapter-statusGET /api/adapter-status/{id}controlGet adapter status
dvblsPOST /control/controlList DVB devices
scan-initPOST /control/controlStart analyzer
scan-checkPOST /control/controlPoll analyzer
scan-killPOST /control/controlStop analyzer
get-userPOST /control/controlGet user
set-userPOST /control/control; observer for its own recordCreate or update user, Remove user, Change own password
toggle-userPOST /control/controlToggle user
reset-passwordPOST /control/reset-password/none, local connections onlyReset password
sessionsGET /api/sessions, POST /control/control; observer on POST /control/ onlyGet session list
close-sessionPOST /control/controlClose session
statusGET /api/status, POST /control/control; observer on POST /control/ onlyGet status
system-statusGET /api/system-statuscontrolSystem status
versionGET /api/version, POST /control/control, observerVersion
logGET /api/log, POST /control/control; observer on POST /control/ onlyLog
restartPOST /control/controlRestart
load, configPOST /control/ with load, GET /api/configcontrol; observer on POST /control/ onlyDownload configuration
uploadPOST /control/controlUpload configuration
set-settingsPOST /control/controlSet general settings
set-configPOST /control/controlSet configuration key
set-authPOST /control/controlSet HTTP authentication
set-logPOST /control/controlSet log settings
set-serverPOST /control/controlSet server
set-softcamPOST /control/controlSet softcam
test-softcamPOST /control/controlTest softcam
set-casPOST /control/controlSet CAS

The WebSocket event channel, GET {control_path}control/event/, is not a command; it is described in Events API.