Querying API
Use Axiom querying API to create and get query objects.
Authorization and Headers
The only expected headers are the Authorization: Bearer
, which is your API or Personal Token. Learn more about API Token and Org ID.
Using Axiom Node.js library to query data
Axiom maintains the axiom-node to provide official Node.js bindings for the Axiom API.
Install using npm install
:
npm install @axiomhq/axiom-node
If you use the Axiom CLI, run eval $(axiom config export -f)
to configure your environment variables.
Otherwise create a personal token in the Axiom settings and export it as AXIOM_TOKEN
. Set AXIOM_ORG_ID
to the organization ID from the settings page of the organization you want to access.
You can also configure the client using options passed to the constructor of the Client:
const client = new Client({
token: process.env.AXIOM_TOKEN,
orgId: process.env.AXIOM_ORG_ID,
});
Create and use a client like this:
// The purpose of this example is to show how to query a dataset using the Axiom
// Processing Language (APL).
import { Client } from '@axiomhq/axiom-node';
const client = new Client({
token: process.env.AXIOM_TOKEN,
orgId: process.env.AXIOM_ORG_ID,
});
async function query() {
const aplQuery = "['flights'] | where altitude > 49000 and flight != '' ";
const res = await client.query(aplQuery);
if (!res.matches || res.matches.length === 0) {
console.warn('no matches found');
return;
}
for (let matched of res.matches) {
console.log(matched.data);
}
}
query();
In the above example we're querying a dataset containing contemporary flight data obtained from an ADSB antenna. Results may look similar to this:
{
aircraft: null,
altitude: 123600,
category: null,
flight: 'BCI96D ',
hex: '407241',
lat: 50.951285,
lon: -1.347961,
messages: 13325,
mlat: [ 'lat', 'lon', 'track', 'speed', 'vert_rate' ],
now: null,
nucp: 0,
rssi: -13.3,
seen: 3.6,
seen_pos: 19.7,
speed: 260,
squawk: '6014',
tisb: [],
track: 197,
type: null,
vert_rate: 64
}
{
aircraft: null,
altitude: 123600,
category: null,
flight: 'BCI96D ',
hex: '407241',
lat: 50.951285,
lon: -1.347961,
messages: 13325,
mlat: [ 'lat', 'lon', 'track', 'speed', 'vert_rate' ],
now: null,
nucp: 0,
rssi: -13.3,
seen: 4.6,
seen_pos: 20.8,
speed: 260,
squawk: '6014',
tisb: [],
track: 197,
type: null,
vert_rate: 64
}
Further examples can be found in the axiom-node repo.
Querying via Curl using APL
This section provides a guide on how to leverage the power of APL through curl commands. By combining the flexibility of curl with the querying capabilities of APL, users can seamlessly fetch and analyze their data right from the terminal.
Whether you're looking to fetch specific data points, aggregate metrics over time, or filter datasets based on certain criteria, the examples provided here will serve as a foundation to build upon. As you become more familiar with APL's syntax and curl's options, you'll find that the possibilities are vast and the insights you can derive are profound.
Examples
Count of distinct routes
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | summarize Count = dcount(vercel.route)",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Top 5 routes by count
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | summarize Count = dcount(vercel.route)",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Average request duration
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | summarize AvgDuration = avg(vercel.duration)",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Requests with duration greater than 1 second
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | where vercel.duration > 1000",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Top 3 routes with the highest average duration
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | summarize AvgDuration = avg(vercel.duration) by vercel.route | top 3 by AvgDuration desc",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Requests grouped by hour
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | summarize Count = count() by bin(_time, 1h)",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Requests with errors
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "vercel | where vercel.status >= 400",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Getting the most common user agents
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "sample-http-logs | summarize count() by user_agent | top 5 by count()",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Identifying the server data centers with the highest number of requests
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "sample-http-logs | summarize count() by server_datacenter | top 3 by count()",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Identifying the average, minimum, and maximum request duration for each method type
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "sample-http-logs | summarize avg(todouble(req_duration_ms)), min(todouble(req_duration_ms)), max(todouble(req_duration_ms)) by method",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Finding the top 3 URIs accessed via TLS connections with a response body size greater than a specified threshold
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "sample-http-logs | where is_tls == true and todouble(resp_body_size_bytes) > 5000 | summarize count() by uri | top 3 by count()",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Calculating the 95th percentile of the request duration for each server datacenter
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "sample-http-logs | summarize percentile(todouble(req_duration_ms), 95) by server_datacenter",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Active issue contributors
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "github-issue-comment-event | where repo startswith \"kubernetes/\" | where actor !endswith \"[bot]\" | summarize dcount(actor) by bin_auto(_time)",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Top Issue Wranglers
curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \
-H 'Authorization: Bearer $API_TOKEN' \
-H 'Accept: application/json' \
-H 'Accept-Encoding: gzip' \
-H 'Content-Type: application/json' \
-d '{
"apl": "github-issues-event | where (actor !endswith \"[bot]\" and repo startswith \"cockroachdb/\" and actor !~ \"cockroach-teamcity\") | summarize topk(actor, 5) by bin_auto(_time), action",
"startTime": "2023-08-15T00:00:00Z",
"endTime": "2023-08-22T00:00:00Z"
}'
Using Curl to query the API
POST api.axiom.co/v1/datasets/\{id\}/query
curl -X 'POST' \
'https://api.axiom.co/v1/datasets/<dataset_id>/query?saveAsKind=<save_as_kind_query>&streaming-duration=<streaming_duration>&nocache=true' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <$API_TOKEN>' \
-d '{
"aggregations": [
{
"alias": "string",
"argument": {},
"field": "string",
"op": "count"
}
],
"continuationToken": "string",
"cursor": "string",
"endTime": "string",
"filter": {
"caseSensitive": true,
"children": [
"string"
],
"field": "string",
"op": "and",
"value": {}
},
"groupBy": [
"string"
],
"includeCursor": true,
"limit": 0,
"order": [
{
"desc": true,
"field": "string"
}
],
"project": [
{
"alias": "string",
"field": "string"
}
],
"queryOptions": {
"against": "string",
"againstStart": "string",
"againstTimestamp": "string",
"caseSensitive": "string",
"containsTimeFilter": "string",
"datasets": "string",
"displayNull": "string",
"editorContent": "string",
"endColumn": "string",
"endLineNumber": "string",
"endTime": "string",
"integrationsFilter": "string",
"openIntervals": "string",
"quickRange": "string",
"resolution": "string",
"startColumn": "string",
"startLineNumber": "string",
"startTime": "string",
"timeSeriesView": "string"
},
"resolution": "string",
"startTime": "string",
"virtualFields": [
{
"alias": "string",
"expr": "string"
}
]
}'
Response Example
Response code 200 and the response body:
{
"buckets": {
"series": [
{
"endTime": "2022-07-26T03:00:48.925Z",
"groups": [
{
"aggregations": [
{
"op": "string",
"value": {}
}
],
"group": {
"additionalProp1": {},
"additionalProp2": {},
"additionalProp3": {}
},
"id": 0
}
],
"startTime": "2022-07-26T03:00:48.925Z"
}
],
"totals": [
{
"aggregations": [
{
"op": "string",
"value": {}
}
],
"group": {
"additionalProp1": {},
"additionalProp2": {},
"additionalProp3": {}
},
"id": 0
}
]
},
"fieldsMeta": [
{
"description": "string",
"hidden": true,
"name": "string",
"type": "string",
"unit": "string"
}
],
"matches": [
{
"_rowId": "string",
"_sysTime": "2022-07-26T03:00:48.925Z",
"_time": "2022-07-26T03:00:48.925Z",
"data": {
"additionalProp1": {},
"additionalProp2": {},
"additionalProp3": {}
}
}
],
"status": {
"blocksExamined": 0,
"cacheStatus": 0,
"continuationToken": "string",
"elapsedTime": 0,
"isEstimate": true,
"isPartial": true,
"maxBlockTime": "2022-07-26T03:00:48.925Z",
"messages": [
{
"code": "string",
"count": 0,
"msg": "string",
"priority": "string"
}
],
"minBlockTime": "2022-07-26T03:00:48.925Z",
"numGroups": 0,
"rowsExamined": 0,
"rowsMatched": 0
}
}