User Guide 19.11 documentation
The PVX API exposes multiple functions for the following tasks:
To access most of these functions, you will need some sort of token (such as an API key or a Session ID). See API Keys.
In this documentation, <SERVER>
refers to the hostname or IP
address of the server hosting the API.
This URI is the root of the currently available protocols:
The documentation of the API functions is available at:
https://<SERVER>/api/doc
Warning
The PVX API is served over TLS (hence the https:// and wss:// prefixes).
For security reasons, it is strongly recommended that you install your own SSL certificate into PVX instead of using the pre-installed one.
For more information on security considerations, please read the related section.
The API responses are formatted as JSON.
The response is composed of messages. A single message is returned, except when streaming is enabled (see below).
A message contains a type
attribute:
{
"type": "<message_type>",
"<message_type>": <result>,
"<extra_attribute>": <value>,
"<extra_attribute>": <value>,
...
}
When a request succeeds, a message of type result
is returned.
{
"type": "result",
"result": <return_value>
}
When a request fails, a message of type error
is returned. The
errors are meant to be self-explanatory. For instance, calling a
function with less arguments than expected will return something
similar to:
{
"type": "error",
"error": "TOO-FEW-ARGUMENTS",
"names": ["title", "queries"],
"count": 2
}
The API is also able to stream chunks instead of returning a single response. This method is described in API Streaming.
The echo
function will be used to show how the PVX API interprets
requests. This function has no real interest in itself other than for
testing purposes. As its name suggests, it simply echoes back the
passed arguments.
It will be used to show some of the available input formats.
Accessing the PVX API through HTTP should be straightforward with common HTTP clients.
All the API functions can be called with either the GET
or POST
HTTP
methods. The function arguments are usually passed through the query string.
The simplest API function invocation over HTTP is to specify its name followed by the arguments.
The arguments and their values are delimited by =
. The values are
interpreted as JSON.
https://<SERVER>/api/function?argument1=value1&argument2=value2&...
To use the streaming mode (see API Streaming), use the stream/
prefix before the function’s name.
https://<SERVER>/api/stream/function?argument1=value1&argument2=value2&...
curl is a well-known tool to access different kind of URLs. It should be available on most UNIX-like systems.
The following commands are executed in a POSIX shell.
$ curl 'https://<SERVER>/api/echo?an_integer=42&a_string="the%20answer"&an_array=\["to%20life","the%20universe","and%20everything"\]'
{
"type": "result",
"result": {
"an_integer": 42
"a_string": "the answer",
"an_array": [
"to life",
"the universe",
"and everything"
]
}
}
Notice how the arguments must be escaped to both satisfy curl
and the URL encoding scheme.
Alternative ways to make a similar invocation include:
curl --get 'https://<SERVER>/api/echo' --data-urlencode 'an_integer=42' --data-urlencode 'a_string="the answer"' --data-urlencode 'an_array=["to life", "the universe", "and everything"]'
curl -X POST 'https://<SERVER>/api/echo' --data-urlencode 'an_integer=42' --data-urlencode 'a_string="the answer"' --data-urlencode 'an_array=["to life", "the universe", "and everything"]'
curl -X POST ' https://<SERVER>/api/echo' --form-string 'an_integer=42' --form-string 'a_string="the answer"' --form-string 'an_array=["to life", "the universe", "and everything"]'
curl -H 'Content-Type: application/json' https://<SERVER>/api/echo --data-raw '{"an_integer": 42, "a_string": "the answer", "an_array": ["to life", "the universe", "and everything"]}'
Invoke-WebRequest is PowerShell cmdlet used to retrieve HTTP pages.
The following commands are executed in PowerShell.
Warning
The curl
command may be automatically aliased to Invoke-WebRequest
and
is not compatible with the curl
presented above.
Get-Alias curl | Select-Object -Property DisplayName
DisplayName
-----------
curl -> Invoke-WebRequest
Invoke-WebRequest 'https://<SERVER>/api/echo?an_integer=42&a_string="the%20answer"&an_array=["to%20life","the%20universe","and%20everything"]'
StatusCode : 200
StatusDescription : OK
Content : {
"result": {
"an_array": [
"to life",
"the universe",
"and everything"
],
"a_string": "the answer",
"an_integer": 42
},
"...
RawContent : HTTP/1.1 200 OK
# result truncated for brevity
Easier ways to make a similar invocation include:
Invoke-WebRequest -Method Post 'https://<SERVER>/api/echo' -Form @{an_integer=42; a_string="the answer"; an_array='["to life", "the universe", "and everything"]'}
You could also interpret the JSON content directly, using Invoke-RestMethod
(but this may not work with streaming methods):
$(Invoke-RestMethod -Method Post 'https://<SERVER>/api/echo' -Form @{an_integer=42; a_string="the answer"; an_array='["to life", "the universe", "and everything"]'}).result
an_array a_string an_integer
-------- -------- ----------
{to life, the universe, and everything} the answer 42
PVX’s WebSocket API is largely similar to the HTTP API but the query format has to be adapted to the transport. It is mostly destined to a programmatic usage but the following examples will show a basic utilisation from the CLI.
All communication is done via JSON messages.
A call must be in the following format:
{
"id": "<call_id>",
"<call_type>": "<function_name>",
"args": {"<argument1>": <value1>, "<argument2>": <value2>, ...}
}
Where call_type
is either call
for standard calls or
stream
for streaming calls.
The id
attribute must be an unique value for each call. For
example, you can use a number that is increased at each call, or an
UUID. This id
can be used to cancel an unfinished call.
wscat is a small WebSocket client.
wscat -c 'wss://<SERVER>/api/ws'
connected (press CTRL+C to quit)
> {"id": "example1", "call": "echo", "args": {"an_integer": 42, "a_string": "the answer", "an_array": ["to life", "the universe", "and everything"]}}
< {
"id": "example1",
"type": "result",
"result": {
"an_integer": 42,
"a_string": "the answer",
"an_array": [
"to life",
"the universe",
"and everything"
]
}
}
API URLs should indicate a desired version. This is recommended to ensure that programs using the API will not break when upgrading. For example:
https://<SERVER>/api/0.1/<function>
https://<SERVER>/api/0.1/doc
wss://<SERVER>/api/0.1/ws
If a version is not specified, the API will choose the latest version available.
When upgrading PVX, the meaning of the API version number is as follow:
MINOR
(e.g. API 1.2 → API 1.3) means the API
only added functionalities and is compatible with the previous one
(e.g. a new function or optional arguments have been added),MAJOR
(e.g. API 1.3 → API 2.0) means the API
introduced breaking changes and is most likely incompatible with
the previous one (e.g. a function has been removed or may require
different arguments).In addition to simple calls, the API provides a method to get a stream
of results. Each partial result is returned with a message of type
chunk
, and terminated by a message of type end
. When an error
is encountered, the stream is interrupted with a message of type
error
.
When using HTTP, add stream/
before the function name in the URL.
For example:
https://<SERVER>/api/1.0/stream/query
Example of messages received:
{
"type": "chunk",
"chunk": <partial_result1>
}
{
"type": "chunk",
"chunk": <partial_result2>
}
{
"type": "end",
}
The exact content of the chunks are described by the documentation of each function. A chunk can contains a combination of:
- new values (to be added to the already accumulated ones),
- updated values (that replace previously given values),
- informative values (that are specific to the chunk itself).
Note
Every function can stream its results. Likewise, every functions can be queried without streaming. In this case, if the function is producing several values, they are all accumulated and send all at once when the function terminates.
API keys are the preferred way to programmatically authenticate to the API.
Note
The current GUI (PVX 5.0) doesn’t provide a way to create an API key. You need to use the API itself to create more keys.
In a future release, it will be possible to manage the API keys directly from the GUI.
Warning
An API key provides a full access to the API. Future enhancement will allow greater granularity on their authorized utilisation.
Creating an API key can be done in two steps:
- creating a session from an user account
- creating an API key from this session.
Warning
This method is temporary, and will be replaced by an easier one in a future version.
Creating the session is done with the login
function that expects
a user
and password
argument. In this example we will use the
default user admin
with the password admin
. (In a standard
installation, this account has a different password.)
The resulting HTTP URL is:
https://<SERVER>/api/login?user=admin&password=admin
Querying it will return something similar to:
{
"type": "result",
"result": "session:907c70c2-a78d-43ec-b577-a26b11ab586c"
}
Here, result
contains our session ID, a reusable temporary token
granting access to the API for a certain amount of time.
If something goes wrong, a response of type error
will be returned
instead.
Now that we have a session, we can create an API key. This is done
with the create-api-key
function. For that, we will need to pass
the session ID in the special _session
argument.
Note
It is perfectly fine to use a session ID to use the API, but this is mainly for user interfaces that need to be based on login/password, with a notion of short-lived sessions. So this is not appropriate for program that use the API.
Querying the following URL:
https://<SERVER>/api/create-api-key?name=example&_session=session:907c70c2-a78d-43ec-b577-a26b11ab586c
will generate an API key named example
and return it in the result
:
{
"type": "result",
"result": "secret:ce8e68ec-9048-4c71-87ef-1b7a96dd7567"
}
The result, secret:ce8e68ec-9048-4c71-87ef-1b7a96dd7567
, is your API key
and must be kept secret.
Once you have an API key, it is usable permanently (until you revoke
it) for authenticated calls by passing it as the argument _key
.
For example, to perform a PVQL query such as traffic
(which is the
total traffic that occurred on the last hour by default), combined
with the API key, we get:
https://<SERVER>/api/query?expr=traffic&_key=secret:ce8e68ec-9048-4c71-87ef-1b7a96dd7567
This will return a result containing a list of objects, including one
with a data
entry, that will look as follow:
{
"data": [[[], [136308984336]]],
"meta": {
"accumulated_time": 0.16814637184143066,
"elapsed": 0.16814422607421875,
"sorted": true
}
}
See query
for an explanation of the format used.
If the authentication is invalid (because the credentials are revoked or expired), the result would have been something like this:
{
"type": "error",
"error": "API-AUTHENTICATION-NEEDED",
"path": "query"
}
The session ID and API key can be provided in different way.
The following authentication tokens can be used in HTTP requests:
- session IDs:
- in a cookie, as “
PVX-Session=<Session>
”,- in the query string, as “
_session=<Session>
”.- API keys:
- in the headers of the request, as “
PVX-Authorization: <API_key>
”,- in the query string, as “
_key=<API_key>
”.
The PVX authentication mechanism prevents anybody from getting PVX access without a secret (account credentials, session ID or API key) shared between the client (anyone requesting the PVX API, including the related PVX graphical interface) and the server.
However, the current authentication mechanism needs this secret to be embedded in clear-text in every authentication-needing requests, and the uniqueness of each request is not verified.
This means that, if the communications between the client and the server are not properly encrypted, any eavesdropper can acquire this secret, forge valid requests and exploit the privileges it grants.
This is why PVX server force the use of TLS (aka SSL).
To ensure optimal security, company-specific TLS certificates should be deployed on the server and used by the client to ensure the communication are encrypted and the server identity is verified.
At your own risk, on a testing installation, you could circumvent certificate verification, but it is mostly system or tool dependent.
For example, with curl this is done with the --insecure
option:
curl --insecure 'https://<SERVER>/api/...'
And with Invoke-WebRequest this is done with the -SkipCertificateCheck
option:
Invoke-WebRequest -SkipCertificateCheck 'https://<SERVER>/api/...'