Fork me on GitHub
Admin/Monitor API

Recent versions of Janus introduced a new feature: an Admin/Monitor API that can be used to ask Janus for more specific information related to sessions and handles. This is especially useful when you want to debug issues at the media level.

Note
Right now, this new API mostly allows you to retrieve information, but only act on part of it: for more interaction (e.g., to force a session removal), you can rely on the existing RESTful, WebSockets, RabbitMQ, MQTT, Nanomsg and UnixSockets API for the purpose. Besides, notice that this is a pull-based API. If you're interested in asynchronous notifications about the internal state of core and plugins, check the recently added janus_eventhandler mechanism instead.

The API, for security reasons, is typically not enabled by default in any of the transport plugins: that's definitely the case for the stock transport plugins, for instance, while additional, third party plugins may choose to expose the functionality without requiring any tweaking. As to the existing transport, you can enable the admin API by editing the [ admin ] section in the related transport configuration file (e.g., janus.transport.http.jcfg for the REST interface, to use the admin API over HTTP). The configuration is pretty much the same as the one for the Janus API. In addition, you can configure restrictions in the form of a password/secret that clients need to provide or other transport-specific ones.

For what concerns the syntax, it's very similar to the RESTful, WebSockets, RabbitMQ, MQTT, Nanomsg and UnixSockets API and so this page will briefly discuss the differences. Notice that, when using WebSockets, you'll have to use janus-admin-protocol as the subprotocol, instead of the janus-protocol of the regular Janus API.

Admin API requests

There are several different requests that this API implementents, so, to make this documentation easier to read and the functionality easier to identify, we can group requests depending on what they provide.

Generic requests

Configuration-related requests

Token-related requests

Session-related requests

Handle- and WebRTC-related requests

Event handlers-related requests

Helper requests

Admin API syntax

Following the same spirit of the RESTful, WebSockets, RabbitMQ, MQTT, Nanomsg and UnixSockets API these methods need to be invoked on the right path and/or providing the right session_id and handle_id identifiers. Specifically, the following requests must be invoked without any session/handle information, as they're global requests:

Here's an example of how such a request and its related response might look like:

POST /admin
{
        "janus" : "list_sessions",
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.jcfg, if any>"
}
{
        "janus" : "success",
        "transaction" : "<same as the request>",
        "sessions" : [
                <session ID #1>,
                <session ID #2>,
                [..]
                <session ID #n>
        ]
}

On the other hand, some requests may be targeting a specific session, in which case a session_id property must be provided. Specifically, these are the requests that do need a valid session identifier:

Using the REST API, this can be done by appending the session identifier (e.g., one of the ID returned by a list_sessions call) to the API root, but a more generic approach that works for all transports is to just specify a session_id property in the request, e.g.:

POST /admin/12345678
{
        "janus" : "list_handles",
        "session_id" : 12345678,
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.jcfg, if any>"
}
{
        "janus" : "success",
        "transaction" : "<same as the request>",
        "session_id" : 12345678,
        "handles" : [
                <handle ID #1>,
                <handle ID #2>,
                [..]
                <handle ID #n>
        ]
}

Finally, some requests need not only a valid session identifier, but a handle identifier as well, as they may address a specific handle that the Janus instance is serving. It is the case for all requests that address a specific handle and/or the related PeerConnection, namely:

The following is an example of how a handle_info call addressing a specific handle might look like. Since this is a handle-specific request, the correct handle identifier must be referenced, e.g., by appending the ID to the session it belongs to or adding a handle_id attribute besides the session_id parent:

POST /admin/12345678/98765432
{
        "janus" : "handle_info",
        "session_id" : 12345678,
        "handle_id" : 98765432,
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.jcfg, if any>"
}
{
        "janus" : "success",
        "transaction" : "<same as the request>",
        "session_id" : 12345678,
        "handle_id" : 98765432,
        "info" : {
                "session_id" : 12345678,
                "session_last_activity": 7927759122,
                "session_transport": "janus.transport.websockets",
                "handle_id" : 98765432,
                "opaque_id": "echotest-YZcsLRCI4uSV",
                "loop-running": true,
                "created": 18695669309,
                "current_time": 18706199704,
                "plugin": "janus.plugin.echotest",
                "plugin_specific": {
                        // plugin specific (e.g., EchoTest internals)
                },
                "flags": {
                        // flags
                },
                "agent-created": 18696092523,
                "ice-mode": "full",
                "ice-role": "controlled",
                "sdps": {
                        "profile": "UDP/TLS/RTP/SAVPF",
                        "local": "v=0[..]",
                        "remote": "v=0[..]"
                },
                "queued-packets": 0,
                "streams": [
                        // WebRTC info, including SSRCs, codecs, ICE and DTLS states, RTCP stats, etc.
                ]
        }
}

With respect to the handle_info request we used as an example, here, the actual content of the last response is omitted for brevity, but you're welcome to experiment with it in order to check whether more information (of a different nature, maybe) may be useful to have. In particular, you may want to play with the plugin-specific details, as different plugins will return different information according to what they provide: for instance, the VideoRoom plugin might clarify whether a handle is being used for publishing media or for receiving it, and what are the involved IDs, the current status of the delivery, and so on. At the same time, the streams object will contain invaluable details related to the WebRTC PeerConnection associated with the handle, as in input/output statistics statistics (bytes, bytes per seconds, NACKs, etc.) or the SDP/ICE/DTLS states. Notice that the information as returned by the Admin API here is just a snapshot: if you're more interested in how this information evolves in a more dynamic way, you may want to start using the Event Handlers instead, which return pretty much the same information, but conveying it as dynamic events pushed to an application you control.

Capturing unencrypted WebRTC traffic

As anticipated, you can also enable/disable the dumping of the RTP/RTCP packets a handle is sending and receiving to a pcap or text2pcap file. This is especially useful for debugging reasons, e.g., to check whether or not there are issues in a specific packet Janus is sending or receiving with tools like Wireshark. Notice that this is not supposed to be used for recording Janus streams: while it can be used for that, the janus_recorder utility is much more suited for the task, and is what all plugins make use of when they're interested in Recordings .

The syntax for the start_pcap and start_text2pcap commands is trivial, and apart from the command name pretty much the same: all you need to specify are information on the handle to dump, information on the target file (target folder and filename), and whether to truncate packets or not before dumping them:

POST /admin/12345678/98765432
{
        "janus" : "start_pcap",         // Use start_text2pcap for a text file instead
        "folder" : "<folder to save the dump to; optional, current folder if missing>",
        "filename" : "<filename of the dump; optional, random filename if missing>",
        "truncate" : "<number of bytes to truncate packet at; optional, truncate=0 (don't truncate) if missing>",
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.jcfg, if any>"
}

If successful, the full path of the dump file can be obtained by doing a handle_info request. A stop_pcap or start_text2pcap command is even easier to generate, as it doesn't need any parameter:

POST /admin/12345678/98765432
{
        "janus" : "stop_pcap",          // Use stop_text2pcap if you started a text-based capture
        "transaction" : "<random alphanumeric string>",
        "admin_secret" : "<password specified in janus.jcfg, if any>"
}