# Axiom documentation --- # Changelog Source: https://axiom.co/docs/changelog Axiom ships continuously. Read the latest release notes on the [Axiom changelog](https://axiom.co/changelog). This section will become the first-party home for product updates as the changelog publishing workflow moves into the documentation platform. --- # Quickstart Source: https://axiom.co/docs/getting-started This guide takes you from foundational knowledge to advanced proficiency with Axiom. The sections are structured to build upon one another but can also serve as standalone references. By the end, you can independently query data, diagnose performance, derive insights, and set up proactive alerting. ## Axiom fundamentals [#axiom-fundamentals] Axiom is the modern machine data platform. Machine data is any record a system produces: logs, distributed traces, metrics, and events like product analytics, marketing attribution, or security audit trails. Axiom stores and queries all of it through one engine. **Datasets** store related machine data, similar to a table in a traditional database. For example, the Axiom Playground includes datasets like `sample-http-logs` for HTTP request logs and `github-push-event` for GitHub activity. **Fields** are named pieces of data on each record, like columns in a spreadsheet. Fields have a name (for example, `status`, `resp_body_size_bytes`, `geo.city`) and a value. Axiom supports various data types including strings, numbers, booleans, and complex JSON objects. * **Single dataset:** Use one dataset when events share many common fields and you often query them together. * **Multiple datasets:** Split into multiple datasets when the data is structurally different or serves entirely different use cases. This prevents a single dataset from accumulating fields that are only relevant to a small subset of its events. ## Send data to Axiom [#send-data-to-axiom] You can send your first event with a single HTTP request: ```shell wrap curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/x-ndjson' \ -d '{ "http": { "request": { "method": "GET", "duration_ms": 231 }, "response": { "body": { "size": 3012 } } }, "url": { "path": "/download" } }' ``` To send events continuously, Axiom supports a wide range of tools and libraries: * **[OpenTelemetry](/send-data/opentelemetry)** for industry-standard instrumentation of traces, logs, and metrics. * **[Axiom API](/restapi/ingest)** for direct HTTP ingestion from any language or platform. * **Language libraries** for [JavaScript](/guides/javascript), [Python](/guides/python), [Go](/guides/go), [Rust](/guides/rust), [.NET](/guides/send-logs-from-dotnet), and more. * **Log shippers** like [Vector](/send-data/vector), [Fluent Bit](/send-data/fluent-bit), and [Logstash](/send-data/logstash). * **Platform integrations** for [AWS](/send-data/cloudwatch), [Kubernetes](/send-data/kubernetes), [Vercel](/apps/vercel), and [Cloudflare Logpush](/apps/cloudflare-logpush). For the full list, see [Methods for sending data](/send-data/methods). ## Explore your data [#explore-your-data] Start by identifying the correct dataset in the [Datasets tab](https://app.axiom.co/datasets). You can explore the fields within a dataset to find relevant information. For example, in `sample-http-logs` you might look at `resp_header_size_bytes` (response size), `status` (HTTP status code), and `geo.country` (geographic origin). Pay attention to field data types. A field stored as a number behaves differently than one stored as a string. The schema view in the Datasets tab shows the type for each field. ## Build your first queries [#build-your-first-queries] You typically interact with this data by creating queries using one of the following interfaces: * **[Builder](/query-data/explore):** A point-and-click interface that helps you build filters and aggregations without writing code. It's excellent for simple, quick-look analyses. * **[Editor](/query-data/query-editor)**: An interface where you can write queries using powerful, text-based query languages for sophisticated analysis. Use [APL (Axiom Processing Language)](/apl/introduction) for logs, traces, and events, and [MPL (Metrics Processing Language)](/mpl/introduction) for metrics. * **[Axiom API](/restapi/query)**: Query your data programmatically. * **[AI-assisted query building](/query-data/query-editor#generate-query-using-natural-language)**: Generate APL queries from natural language descriptions after pressing Cmd+K (macOS) or Ctrl+K (Windows/Linux) in the Query tab. * **[MCP Server](/console/intelligence/mcp-server) and [Skills](/console/intelligence/skills)**: Enable AI agents to query your data. Agents without an existing organization can [provision their own temporary organization](/console/intelligence/agent-created-orgs). An APL query starts with a data source, followed by operators connected by the pipe `|` character. Each pipe takes the output of the previous line and uses it as input for the next, allowing you to chain operations. A common pattern is dataset, filter (`where`), transform (`extend`), analyze (`summarize`). This example counts distinct users per day, grouped by HTTP method: ```kusto ['sample-http-logs'] | summarize dcount(id) by bin(_time, 1d), method ``` [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%5Cn%7C%20summarize%20dcount\(id\)%20by%20bin\(_time%2C%201d\)%2C%20method%22%2C%22queryOptions%22%3A%7B%22quickRange%22%3A%2230d%22%7D%7D) * `['sample-http-logs']` selects the dataset. * `|` passes the data to the next operator. * `summarize` groups rows that share values in the `by` clause. * `dcount(id)` calculates the distinct count of the `id` field. This is a probabilistic function that provides a highly accurate approximation and runs faster than an exact count. * `by bin(_time, 1d), method` groups by time binned into 1-day intervals and by HTTP method. * Start with Builder to understand the basic structure of a query, then switch to Editor to refine it. * Use the AI assistant as a learning tool. Generate a query and then study its structure to understand the APL. * Use the `where` operator early to narrow down events. This is important for performance. * Review your team's saved queries in Axiom to learn from real-world examples. * The full list of functions and operators is available in the [Query reference](/apl/overview). ## Set up monitors [#set-up-monitors] [Monitors](/monitor-data/monitors) run queries on a schedule and trigger notifications when conditions are met. This moves you from reactive investigation to proactive awareness. * **[Threshold monitors](/monitor-data/threshold-monitors)** trigger when an aggregated value crosses a threshold (for example, error counts above 100 in 5 minutes). This is the most common type. * **[Match monitors](/monitor-data/match-monitors)** trigger for each individual event that matches a specific pattern (for example, a critical error message). Use these sparingly for high-volume events. * **[Anomaly monitors](/monitor-data/anomaly-monitors)** use machine learning to detect unexpected deviations from a historical baseline, without a static threshold. This example creates a threshold monitor to get a notification if the number of server errors exceeds a threshold. 1. Write and test the query: ```kusto ['sample-http-logs'] | where status >= 500 | summarize error_count = count() ``` 2. Go to **Monitors** tab and create a new threshold monitor. 3. Paste your query and set the trigger condition, for example, `When error_count is above 50`. 4. Set the schedule, for example, evaluate every 5 minutes. 5. Select or create a [notifier](/monitor-data/notifiers-overview) (Slack, PagerDuty, email, and more). * Customize the notifier description to include important context such as a link to a relevant dashboard. * Avoid creating match monitors on high-volume logs without specific filters. This can lead to excessive notifications. ## Build dashboards [#build-dashboards] [Dashboards](/dashboards/create) are collections of saved queries visualized as charts, tables, and other elements. They provide a single view for monitoring a service, tracking an experiment, or sharing key metrics. This example creates a dashboard to monitor HTTP request performance. **Element 1: P75 and P95 latency (time series)** This query calculates the 75th and 95th percentiles of request duration and displays them as a time series. ```kusto ['sample-http-logs'] | summarize P75 = percentile(req_duration_ms, 75), P95 = percentile(req_duration_ms, 95) by bin_auto(_time) ``` [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%5Cn%7C%20summarize%5Cn%20%20%20%20P75%20%3D%20percentile\(req_duration_ms%2C%2075\)%2C%5Cn%20%20%20%20P95%20%3D%20percentile\(req_duration_ms%2C%2095\)%5Cn%20%20by%20bin_auto\(_time\)%22%2C%22queryOptions%22%3A%7B%22quickRange%22%3A%2230d%22%7D%7D) **Element 2: Requests by country (table)** This query counts the number of requests by country and displays them as a table. ```kusto ['sample-http-logs'] | summarize request_count = count() by ['geo.country'] | sort by request_count desc ``` [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%5Cn%7C%20summarize%20request_count%20%3D%20count\(\)%20by%20%5B'geo.country'%5D%5Cn%7C%20sort%20by%20request_count%20desc%22%2C%22queryOptions%22%3A%7B%22quickRange%22%3A%2230d%22%7D%7D) **Element 3: Total distinct users (statistic)** This query counts the number of distinct users and displays them as a statistic. ```kusto ['sample-http-logs'] | summarize dcount(id) ``` [Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%5Cn%7C%20summarize%20dcount\(id\)%22%2C%22queryOptions%22%3A%7B%22quickRange%22%3A%2230d%22%7D%7D) * Give dashboards and their elements clear, descriptive names. * Use dashboard filters to allow viewers to slice data by dimensions like region, status code, or service. * Avoid cluttering a single dashboard with unrelated metrics. Create separate dashboards for different use cases. ## What's next [#whats-next] * [APL introduction](/apl/introduction) for the full query language reference. * [Sample queries](/apl/tutorial) for real-world APL examples you can run in the Playground. * [Send data to Axiom](/send-data/methods) to connect your own data sources. * [Monitor examples](/monitor-data/monitor-examples) for more alerting patterns. --- # What is Axiom? Source: https://axiom.co/docs/introduction Axiom is a data platform designed to efficiently collect, store, and analyze event and telemetry data at massive scale. At its core, Axiom combines a high-performance, proprietary data store with an intelligent Console, helping teams reach actionable insights from their data faster. Trusted by 30,000+ organizations, from high-growth startups to global enterprises. ## Components [#components] Axiom consists of two purpose-built data stores supported by a unified console experience: ### EventDB [#eventdb] Robust, cost-effective, and scalable datastore specifically optimized for timestamped event data. Built from the ground up to handle the vast volumes and high velocity of event ingestion, EventDB ensures: * **Scalable data loading:** Events are ingested seamlessly without complex middleware, scaling linearly with no single points of failure. * **Extreme compression:** Tuned storage format compresses data 25-50x, significantly reducing storage costs and ensuring data remains queryable at any time. * **Serverless querying:** Axiom spins up ephemeral, serverless runtimes on-demand to execute queries efficiently, minimizing idle compute resources and costs. ### MetricsDB [#metricsdb] Dedicated metrics datastore engineered specifically for high-cardinality time-series data. Unlike traditional metrics solutions that penalize you for dimensional complexity, MetricsDB embraces high-cardinality tags as a design principle: * **High-cardinality native:** Store metrics with high-cardinality dimensional tags without performance degradation or cost penalties. * **Optimized storage:** Purpose-built storage format designed for time-series workloads delivers efficient compression and fast aggregations across millions of unique tag combinations. * **Thoughtful constraints:** Design choices prioritize the most common metrics use cases while maintaining exceptional performance. For more information, see [Axiom’s architecture](/platform-overview/architecture). ### Console [#console] Intuitive web app built for exploration, visualization, and monitoring of your data. * **Real-time exploration:** Effortlessly query and visualize data streams in real-time, providing instant clarity on operational and business conditions. * **Dynamic visualizations:** Generate insightful visualizations, from straightforward counts to sophisticated aggregations, tailored specifically to your needs. * **Robust monitoring:** Set up threshold-based and anomaly driven alerts, ensuring proactive visibility into potential issues. ## Why choose Axiom? [#why-choose-axiom] * **Cost-efficiency:** Axiom dramatically lowers data ingestion and storage costs compared to traditional observability and logging solutions. * **Flexible insights:** Real-time query capabilities and an increasingly intelligent UI help pinpoint issues and opportunities without sampling. * **One platform, many use cases:** Use Axiom for observability (logs, metrics, traces), LLM observability, product analytics, and any other machine data workload. ## Getting started [#getting-started] * [Learn more about Axiom’s features](/platform-overview/features). * [Explore the interactive demo playground](https://play.axiom.co/). * [Create your own organization](https://app.axiom.co/register). * Building with AI agents? Agents can [provision their own temporary organization](/console/intelligence/agent-created-orgs) with a single API request. --- # API limits Source: https://axiom.co/docs/restapi/api-limits Axiom limits the number of calls a user (and their organization) can make over a certain period of time to ensure fair usage and to maintain the quality of service for everyone. Axiom systems closely monitor API usage and if a user exceeds any thresholds, Axiom temporarily halts further processing of requests from that user (and/or organization). This is to prevent any single user or app from overloading the system, which could potentially impact other users' experience. ## Rate Limits [#rate-limits] Rate limits vary and are specified by the following header in all responses: | Header | Description | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `X-RateLimit-Scope` | Indicates if the limits counts against the organisation or personal rate limit. | | `X-RateLimit-Limit` | The maximum number of requests a user is permitted to make per minute. | | `X-RateLimit-Remaining` | The number of requests remaining in the current rate limit window. | | `X-RateLimit-Reset` | The time at which the current rate limit window resets in UTC [epoch seconds](https://en.wikipedia.org/wiki/Unix_time). | **Possible values for X-RateLimit-Scope :** * `user` * `organization` **When the rate limit is exceeded, an error is returned with the status "429 Too Many Requests"**: ```json { "message": "rate limit exceeded", } ``` ## Query Limits [#query-limits] | Header | Description | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | `X-QueryLimit-Limit` | The query cost limit of your plan in Gigabyte Milliseconds (GB\*ms). | | `X-QueryLimit-Remaining` | The remaining query Gigabyte Milliseconds. | | `X-QueryLimit-Reset` | The time at which the current rate limit window resets in UTC [epoch seconds](https://en.wikipedia.org/wiki/Unix_time). | ## Ingest Limits [#ingest-limits] | Header | Description | | ------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `X-IngestLimit-Limit` | The maximum bytes ingested a user is permitted to make per month. | | `X-IngestLimit-Remaining` | The bytes ingested remaining in the current rate limit window. | | `X-IngestLimit-Reset` | The time at which the current rate limit window resets in UTC [epoch seconds](https://en.wikipedia.org/wiki/Unix_time). | Alongside data volume limits, Axiom also monitors the rate of ingest requests. If an organization consistently sends an excessive number of requests per second, far exceeding normal usage patterns, Axiom reserves the right to suspend their ingest to maintain system stability and ensure fair resource allocation for all users. To prevent exceeding these rate limits, it’s highly recommended to use batching clients, which can efficiently manage the number of requests by aggregating data before sending. ## Limits on ingested data [#limits-on-ingested-data] For more information on limits and requirements imposed by Axiom, see [Limits](/reference/limits). --- # Send data to Axiom via API Source: https://axiom.co/docs/restapi/ingest The Axiom REST API accepts the following data formats: * [JSON](#send-data-in-json-format) * [NDJSON](#send-data-in-ndjson-format) * [CSV](#send-data-in-csv-format) This page explains how to send data to Axiom via cURL commands in each of these formats, and how to send data with the [Axiom Node.js library](#send-data-with-axiom-node-js). For more information on choosing an ingest format, see [Optimize data loading](/reference/optimize-usage#optimize-data-loading). For more information on other ingest options, see [Send data](/send-data/methods). For an introduction to the basics of the Axiom API and to the authentication options, see [Introduction to Axiom API](/restapi/introduction). The API requests on this page use the ingest data endpoint. For more information, see the [API reference](/restapi/endpoints/ingestToDataset). The [Ingest data endpoint](/restapi/endpoints/ingestToDataset) only supports API tokens. Personal access tokens (PATs) aren't supported. For more information, see [Tokens](/reference/tokens). ## Send data in JSON format [#send-data-in-json-format] To send data to Axiom in JSON format: 1. Encode the events as JSON objects. 2. Enter the array of JSON objects into the body of the API request. 3. Optional: In the body of the request, set optional parameters such as `timestamp-field` and `timestamp-format`. For more information, see the [ingest data API reference](/restapi/endpoints/ingestToDataset). 4. Set the `Content-Type` header to `application/json`. 5. Set the `Authorization` header to `Bearer API_TOKEN`. 6. Send the POST request to `https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME`. ### Example with grouped events [#example-with-grouped-events] The following example request contains grouped events. The structure of the JSON payload has the scheme of `[ { "labels": { "key1": "value1", "key2": "value2" } }, ]` where the array contains one or more JSON objects describing events. **Example request** ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '[ { "time":"2025-01-12T00:00:00.000Z", "data":{"key1":"value1","key2":"value2"} }, { "data":{"key3":"value3"}, "labels":{"key4":"value4"} } ]' ``` **Example response** ```json { "ingested": 2, "failed": 0, "failures": [], "processedBytes": 219, "blocksCreated": 0, "walLength": 2 } ``` ### Example with nested arrays [#example-with-nested-arrays] **Example request** ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '[ { "axiom": [{ "logging":[{ "observability":[{ "location":[{ "credentials":[{ "datasets":[{ "first_name":"axiom", "last_name":"logging", "location":"global" }], "work":[{ "details":"https://app.axiom.co/", "tutorials":"https://www.axiom.co/blog", "changelog":"https://www.axiom.co/changelog", "documentation": "https://www.axiom.co/docs" }] }], "social_media":[{ "details":[{ "twitter":"https://twitter.com/AxiomFM", "linkedin":"https://linkedin.com/company/axiomhq", "github":"https://github.com/axiomhq" }], "features":[{ "datasets":"view logs", "stream":"live_tail", "explorer":"queries" }] }] }] }], "logs":[{ "apl": "functions" }] }], "storage":[{}] }]} ]' ``` **Example response** ```json { "ingested":1, "failed":0, "failures":[], "processedBytes":1587, "blocksCreated":0, "walLength":3 } ``` ### Example with objects, strings, and arrays [#example-with-objects-strings-and-arrays] **Example request** ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '[{ "axiom": { "logging": { "observability": [ { "apl": 23, "function": "tostring" }, { "apl": 24, "operator": "summarize" } ], "axiom": [ { "stream": "livetail", "datasets": [4, 0, 16], "logging": "observability", "metrics": 8, "dashboard": 10, "alerting": "kubernetes" } ] }, "apl": { "reference": [[80, 12], [30, 40]] } } }]' ``` **Example response** ```json { "ingested":1, "failed":0, "failures":[], "processedBytes":432, "blocksCreated":0, "walLength":4 } ``` ## Send data in NDJSON format [#send-data-in-ndjson-format] To send data to Axiom in NDJSON format: 1. Encode the events as JSON objects. 2. Enter each JSON object in a separate line into the body of the API request. 3. Optional: In the body of the request, set optional parameters such as `timestamp-field` and `timestamp-format`. For more information, see the [ingest data API reference](/restapi/endpoints/ingestToDataset). 4. Set the `Content-Type` header to either `application/json` or `application/x-ndjson`. 5. Set the `Authorization` header to `Bearer API_TOKEN`. Replace `API_TOKEN` with the Axiom API token you have generated. 6. Send the POST request to `https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME`. Replace `DATASET_NAME` with the name of the Axiom dataset where you want to send data. **Example request** ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/x-ndjson' \ -d '{"id":1,"name":"machala"} {"id":2,"name":"axiom"} {"id":3,"name":"apl"} {"index": {"_index": "products"}} {"timestamp": "2016-06-06T12:00:00+02:00", "attributes": {"key1": "value1","key2": "value2"}} {"queryString": "count()"}' ``` **Example response** ```json { "ingested": 6, "failed": 0, "failures": [], "processedBytes": 266, "blocksCreated": 0, "walLength": 6 } ``` ## Send data in CSV format [#send-data-in-csv-format] To send data to Axiom in JSON format: 1. Encode the events in CSV format. The first line specifies the field names separated by commas. Subsequent new lines specify the values separated by commas. 2. Enter the CSV representation in the body of the API request. 3. Optional: In the body of the request, set optional parameters such as `timestamp-field` and `timestamp-format`. For more information, see the [ingest data API reference](/restapi/endpoints/ingestToDataset). 4. Set the `Content-Type` header to `text/csv`. 5. Set the `Authorization` header to `Bearer API_TOKEN`. Replace `API_TOKEN` with the Axiom API token you have generated. 6. Send the POST request to `https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME`. Replace `DATASET_NAME` with the name of the Axiom dataset where you want to send data. **Example request** ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: text/csv' \ -d 'user, name foo, bar' ``` **Example response** ```json { "ingested": 1, "failed": 0, "failures": [], "processedBytes": 28, "blocksCreated": 0, "walLength": 2 } ``` ## Send data with Axiom Node.js [#send-data-with-axiom-nodejs] 1. [Install and configure](/guides/javascript#use-axiomhq-js) the Axiom Node.js library. 2. Encode the events as JSON objects. 3. Pass the dataset name and the array of JSON objects to the `axiom.ingest` function. ```ts axiom.ingest('DATASET_NAME', [{ foo: 'bar' }]); await axiom.flush(); ``` For more information on other libraries you can use to send data, see [Send data](/send-data/methods). ## What’s next [#whats-next] After ingesting data to Axiom, you can [query it via API](/restapi/query) or the [Axiom Console](/query-data/explore). --- # Get started with Axiom API Source: https://axiom.co/docs/restapi/introduction You can use the Axiom API (Application Programming Interface) to send data to Axiom, query data, and manage resources programmatically. This page covers the basics for interacting with the Axiom API. ## API basics [#api-basics] Axiom API follows the REST architectural style and uses JSON for serialization. You can send API requests to Axiom with curl or API tools such as [Postman](https://www.postman.com/). For example, the following curl command ingests data to an Axiom dataset: ```bash curl -X 'POST' 'https://AXIOM_DOMAIN/v1/ingest/DATASET_NAME' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '[ { "axiom": "logs" } ]' ``` For more information, see [Send data to Axiom via API](/restapi/ingest) and [Ingest data endpoint](/restapi/endpoints/ingestToDataset). ## Base domain [#base-domain] The base domain of an API request depends on the following: * To ingest data, use the [Ingest data endpoint](/restapi/endpoints/ingestToDataset) with the base domain of your edge deployment. For more information on edge deployments, see [Edge deployments](/reference/edge-deployments). * For all other API endpoints, use the base domain `https://api.axiom.co`. ## Content type [#content-type] Encode the body of API requests as JSON objects and set the `Content-Type` header to `application/json`. Unless otherwise specified, Axiom encodes all responses (including errors) as JSON objects. ## Authentication [#authentication] To prove that API requests come from you, you must include forms of authentication called tokens in your API requests. Axiom offers two types of tokens: * [API tokens](/reference/tokens#api-tokens) let you control the actions that can be performed with the token. For example, you can specify that requests authenticated with a certain API token can only query data from a particular dataset. * [Personal access tokens (PATs)](/reference/tokens#personal-access-tokens-pat) provide full control over your Axiom account. Requests authenticated with a PAT can perform every action you can perform in Axiom. When possible, use API tokens instead of PATs. If you use an API token for authentication, include the API token in the `Authorization` header. ```bash Authorization: Bearer API_TOKEN ``` If you use a PAT for authentication, include the PAT in the `Authorization` header and the org ID in the `x-axiom-org-id` header. For more information, see [Determine org ID](/reference/tokens#determine-org-id). ```bash Authorization: Bearer API_TOKEN x-axiom-org-id: ORG_ID ``` If authentication is unsuccessful for a request, Axiom returns the error status code `403`. ## Data types [#data-types] Below is a list of the types of data used within the Axiom API: | Name | Definition | Example | | ----------- | ----------------------------------------------------------------- | ------------------------ | | **ID** | A unique value used to identify resources. | "io12h34io1h24i" | | **String** | A sequence of characters used to represent text. | "string value" | | **Boolean** | A type of two possible values representing true or false. | true | | **Integer** | A number without decimals. | 4567 | | **Float** | A number with decimals. | 15.67 | | **Map** | A data structure with a list of values assigned to a unique key. | \{ "key": "value" } | | **List** | A data structure with only a list of values separated by a comma. | `["value", 4567, 45.67]` | ## What’s next [#whats-next] * [Ingest data via API](/restapi/ingest) * [Query data via API](/restapi/query) --- # Pagination in Axiom API Source: https://axiom.co/docs/restapi/pagination Pagination allows you to retrieve responses in manageable chunks. You can use pagination for the following endpoints: * [Run Query](/restapi/endpoints/queryApl) * [Run Query (Legacy)](/restapi/endpoints/queryDataset) ## Pagination mechanisms [#pagination-mechanisms] You can use one of the following pagination mechanisms: * [Pagination based on timestamp](#timestamp-based-pagination) (stable) * [Pagination based on cursor](#cursor-based-pagination) (public preview) Axiom recommends timestamp-based pagination. Cursor-based pagination is in public preview and may return unexpected query results. ## Timestamp-based pagination [#timestamp-based-pagination] The parameters and mechanisms differ between the current and legacy endpoints. ### Run Query [#run-query] To use timestamp-based pagination with the Run Query endpoint: * Include the [limit operator](/apl/tabular-operators/limit-operator) in the APL query of your API request. The argument of this operator determines the number of events to display per page. * Use `sort by _time asc` or `sort by _time desc` in the APL query. This returns the results in ascending or descending chronological order. For more information, see [sort operator](/apl/tabular-operators/sort-operator). * Specify `startTime` and `endTime` in the body of your API request. ### Run Query (Legacy) [#run-query-legacy] To use timestamp-based pagination with the legacy Run Query endpoint: * Add the `limit` parameter to the body of your API request. The value of this parameter determines the number of events to display per page. * Add the `order` parameter to the body of your API request. In the value of this parameter, order the results by time in either ascending or descending chronological order. For example, `[{ "field": "_time", "desc": true }]`. For more information, see [order operator](/apl/tabular-operators/order-operator). * Specify `startTime` and `endTime` in the body of your API request. ## Page through the result set [#page-through-the-result-set] Use the timestamps as boundaries to page through the result set. ### Queries with descending order [#queries-with-descending-order] To go to the next page of the result set for queries with descending order (`_time desc`): 1. Determine the timestamp of last item on the current page. This is the least recent event. 2. Optional: Subtract 1 nanosecond from the timestamp. 3. In your next request, change the value `endTime` parameter in the body of your API request to the timestamp of the last item (optionally, minus 1 nanosecond). Repeat this process until the result set is empty. ### Queries with ascending order [#queries-with-ascending-order] To go to the next page of the result set for queries with ascending order (`_time asc`): 1. Determine the timestamp of last item on the current page. This is the most recent event. 2. Optional: Add 1 nanosecond to the timestamp. 3. In your next request, change the value `startTime` parameter in the body of your API request to the timestamp of the last item (optionally, plus 1 nanosecond). Repeat this process until the result set is empty. ### Deduplication mechanism [#deduplication-mechanism] In the procedures above, the steps about incrementing the timestamp are optional. If you increment the timestamp, there is a risk of duplication. If you don’t increment the timestamp, there is a risk of overlap. Duplicated data is possible for many reasons, such as backfill or natural duplication from external data sources. For these reasons, regardless of the method you choose (increment or not increment the timestamp, sort by descending or ascending order), Axiom recommends you implement some form of deduplication mechanism in your pagination script. ### Limits [#limits] Both the Run Query and the Run Query (Legacy) endpoints allow request-based limit configuration. This means that the limit they use is the lowest of the following: the query limit, the request limit, and Axiom’s server-side internal limit. Without a query or request limit, Axiom currently defaults to the limit of 1,000 events per page. For the pagination of datasets that are greater than 1,000 events, Axioms recommends specifying the same limit in the request and the APL query to avoid the default value and contradictory limits. ### Examples [#examples] #### Example request Run Query [#example-request-run-query] ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "apl": "DATASET_NAME | sort by _time desc | limit 100", "startTime": "2024-11-30T00:00:00.000Z", "endTime": "2024-11-30T23:59:59.999Z" }' ``` #### Example request Run Query (Legacy) [#example-request-run-query-legacy] ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/DATASET_NAME/query' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "startTime": "2024-11-30T00:00:00.000Z", "endTime": "2024-11-30T23:59:59.999Z", "limit": 100, "order": [{ "field": "_time", "desc": true }] }' ``` #### Example request to page through the result set [#example-request-to-page-through-the-result-set] Example request to go to next page for Run Query: ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "apl": "DATASET_NAME | sort by _time desc | limit 100", "startTime": "2024-11-30T00:00:00.000Z", "endTime": "2024-11-30T22:59:59.999Z" }' ``` Example request to go to next page for Run Query (Legacy): ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/DATASET_NAME/query' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "startTime": "2024-11-30T00:00:00.000Z", "endTime": "2024-11-30T22:59:59.999Z", "limit": 100, "order": [{ "field": "_time", "desc": true }] }' ``` ## Cursor-based pagination [#cursor-based-pagination] Cursor-based pagination is in public preview and may return unexpected query results. Axiom recommends timestamp-based pagination. The parameters and mechanisms differ between the current and legacy endpoints. ### Run Query [#run-query-1] To use cursor-based pagination with the Run Query endpoint: * Include the [`limit` operator](/apl/tabular-operators/limit-operator) in the APL query of your API request. The argument of this operator determines the number of events to display per page. * Use `sort by _time asc` or `sort by _time desc` in the APL query. This returns the results in ascending or descending chronological order. For more information, see [sort operator](/apl/tabular-operators/sort-operator). * Specify `startTime` and `endTime` in the body of your API request. ### Run Query (Legacy) [#run-query-legacy-1] To use cursor-based pagination with the legacy Run Query endpoint: * Add the `limit` parameter to the body of your API request. The value of this parameter determines the number of events to display per page. * Add the `order` parameter to the body of your API request. In the value of this parameter, order the results by time in either ascending or descending chronological order. For example, `[{ "field": "_time", "desc": true }]`. For more information, see [order operator](/apl/tabular-operators/order-operator). * Specify `startTime` and `endTime` in the body of your API request. ### Response format [#response-format] Contains metadata about the response including pagination information. Cursor for the first item in the current page. Cursor for the last item in the current page. Total number of rows matching the query. Contains the list of returned objects. ## Page through the result set [#page-through-the-result-set-1] To page through the result set, add the `cursor` parameter to the body of your API request. Optional. A cursor for use in pagination. Use the cursor string returned in previous responses to fetch the next or previous page of results. The `minCursor` and `maxCursor` fields in the response are boundaries that help you page through the result set. For queries with descending order (`_time desc`), use `minCursor` from the response as the `cursor` in your next request to go to the next page. You reach the end when your provided `cursor` matches the `minCursor` in the response. For queries with ascending order (`_time asc`), use `maxCursor` from the response as the `cursor` in your next request to go to the next page. You reach the end when your provided `cursor` matches the `maxCursor` in the response. If the query returns fewer results than the specified limit, paging can stop. ### Examples [#examples-1] #### Example request Run Query [#example-request-run-query-1] ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "apl": "DATASET_NAME | sort by _time desc | limit 100", "startTime": "2024-01-01T00:00:00.000Z", "endTime": "2024-01-31T23:59:59.999Z" }' ``` #### Example request Run Query (Legacy) [#example-request-run-query-legacy-1] ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/DATASET_NAME/query' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "startTime": "2024-01-01T00:00:00.000Z", "endTime": "2024-01-31T23:59:59.999Z", "limit": 100, "order": [{ "field": "_time", "desc": true }] }' ``` #### Example response [#example-response] ```json { "status": { "rowsMatched": 2500, "minCursor": "0d3wo7v7e1oii-075a8c41710018b9-0000ecc5", "maxCursor": "0d3wo7v7e1oii-075a8c41710018b9-0000faa3" }, "matches": [ // ... events ... ] } ``` #### Example request to page through the result set [#example-request-to-page-through-the-result-set-1] To page through the result set, use the appropriate cursor value in your next request. For more information, see [Page through the result set](#page-through-the-result-set). Example request to go to next page for Run Query: ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/_apl?format=tabular' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "apl": "DATASET_NAME | sort by _time desc | limit 100", "startTime": "2024-01-01T00:00:00.000Z", "endTime": "2024-01-31T23:59:59.999Z", "cursor": "0d3wo7v7e1oii-075a8c41710018b9-0000ecc5" }' ``` Example request to go to next page for Run Query (Legacy): ```bash curl -X 'POST' 'https://api.axiom.co/v1/datasets/DATASET_NAME/query' \ -H 'Authorization: Bearer API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "startTime": "2024-01-01T00:00:00.000Z", "endTime": "2024-01-31T23:59:59.999Z", "limit": 100, "order": [{ "field": "_time", "desc": true }], "cursor": "0d3wo7v7e1oii-075a8c41710018b9-0000ecc5" }' ``` --- # Query data via Axiom API Source: https://axiom.co/docs/restapi/query This page explains how to query data via the Axiom API using the following: * [cURL](#query-data-with-curl) * [Axiom JavaScript library (`@axiomhq/js`)](#query-data-with-the-axiom-javascript-library) For an introduction to the basics of the Axiom API and to the authentication options, see [Introduction to Axiom API](/restapi/introduction). The API requests on this page use the query data endpoint. For more information, see the [API reference](/restapi/endpoints/queryApl). ## Query data with cURL [#query-data-with-curl] To query data with cURL: 1. Build the APL query. For more information, see [Introduction to APL](/apl/introduction). 2. Encode the APL query as a JSON object and enter it into the body of the API request. 3. Optional: In the body of the request, set optional parameters such as `startTime` and `endTime`. For more information, see the [query data API reference](/restapi/endpoints/queryApl). 4. Set the `Content-Type` header to `application/json`. 5. Set the `Authorization` header to `Bearer API_TOKEN`. 6. Send the POST request to one of the following: * For tabular output, use `https://AXIOM_DOMAIN/v1/query/_apl?format=tabular`. * For legacy output, use `https://AXIOM_DOMAIN/v1/query/_apl?format=legacy`. ### Example [#example] ```bash curl --request POST \ --url 'https://AXIOM_DOMAIN/v1/query/_apl?format=tabular' \ --header 'Authorization: Bearer API_TOKEN' \ --header 'Content-Type: application/json' \ --data '{ "apl": "DATASET_NAME | limit 10", "startTime": "string", "endTime": "string" }' ``` **Example response** ```json [expandable] { "format": "tabular", "status": { "elapsedTime": 260650, "minCursor": "0d8q6stroluyo-07c3957e7400015c-0000c875", "maxCursor": "0d8q6stroluyo-07c3957e7400015c-0000c877", "blocksExamined": 4, "blocksCached": 0, "blocksMatched": 0, "rowsExamined": 197604, "rowsMatched": 197604, "numGroups": 0, "isPartial": false, "cacheStatus": 1, "minBlockTime": "2025-03-26T12:03:14Z", "maxBlockTime": "2025-03-26T12:12:42Z" }, "tables": [ { "name": "0", "sources": [ { "name": "DATASET_NAME" } ], "fields": [ { "name": "_sysTime", "type": "datetime" }, { "name": "_time", "type": "datetime" }, { "name": "content_type", "type": "string" }, { "name": "geo.city", "type": "string" }, { "name": "geo.country", "type": "string" }, { "name": "id", "type": "string" }, { "name": "is_tls", "type": "boolean" }, { "name": "message", "type": "string" }, { "name": "method", "type": "string" }, { "name": "req_duration_ms", "type": "float" }, { "name": "resp_body_size_bytes", "type": "integer" }, { "name": "resp_header_size_bytes", "type": "integer" }, { "name": "server_datacenter", "type": "string" }, { "name": "status", "type": "string" }, { "name": "uri", "type": "string" }, { "name": "user_agent", "type": "string" }, { "name": "is_ok_2 ", "type": "boolean" }, { "name": "city_str_len", "type": "integer" } ], "order": [ { "field": "_time", "desc": true } ], "groups": [], "range": { "field": "_time", "start": "1970-01-01T00:00:00Z", "end": "2025-03-26T12:12:43Z" }, "columns": [ [ "2025-03-26T12:12:42.68112905Z", "2025-03-26T12:12:42.68112905Z", "2025-03-26T12:12:42.68112905Z" ], [ "2025-03-26T12:12:42Z", "2025-03-26T12:12:42Z", "2025-03-26T12:12:42Z" ], [ "text/html", "text/plain-charset=utf-8", "image/jpeg" ], [ "Ojinaga", "Humboldt", "Nevers" ], [ "Mexico", "United States", "France" ], [ "8af366cf-6f25-42e6-bbb4-d860ab535a60", "032e7f68-b0ab-47c0-a24a-35af566359e5", "4d2c7baa-ff28-4b1f-9db9-8e6c0ed5a9c9" ], [ false, false, true ], [ "QCD permutations were not solvable in linear time, expected compressed time", "QCD permutations were not solvable in linear time, expected compressed time", "Expected a new layer of particle physics but got a Higgs Boson" ], [ "GET", "GET", "GET" ], [ 1.396373193863436, 0.16252390534308514, 0.4093416175186162 ], [ 3448, 2533, 1906 ], [ 84, 31, 29 ], [ "DCA", "GRU", "FRA" ], [ "201", "200", "200" ], [ "/api/v1/buy/commit/id/go", "/api/v1/textdata/cnfigs", "/api/v1/bank/warn" ], [ "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))" ], [ true, true, true ], [ 7, 8, 6 ] ] } ], "datasetNames": [ "DATASET_NAME" ], "fieldsMetaMap": { "DATASET_NAME": [ { "name": "status", "type": "", "unit": "", "hidden": false, "description": "HTTP status code" }, { "name": "resp_header_size_bytes", "type": "integer", "unit": "none", "hidden": false, "description": "" }, { "name": "geo.city", "type": "string", "unit": "", "hidden": false, "description": "the city" }, { "name": "resp_body_size_bytes", "type": "integer", "unit": "decbytes", "hidden": false, "description": "" }, { "name": "content_type", "type": "string", "unit": "", "hidden": false, "description": "" }, { "name": "geo.country", "type": "string", "unit": "", "hidden": false, "description": "" }, { "name": "req_duration_ms", "type": "float", "unit": "ms", "hidden": false, "description": "Request duration" } ] } } ``` ## Query data with the Axiom JavaScript library [#query-data-with-the-axiom-javascript-library] 1. [Install and configure](/guides/javascript#use-axiomhq-js) the Axiom JavaScript library (`@axiomhq/js`). 2. Build the APL query. For more information, see [Introduction to APL](/apl/introduction). 3. Pass the APL query as a string to the `axiom.query` function. ```ts const res = await axiom.query(`['DATASET_NAME'] | where foo == 'bar' | limit 100`); console.log(res); ``` To run queries within a specific edge deployment, set the `edge` option when you create the client. The client then routes queries to the [edge query endpoint](/restapi/endpoints/queryEdge) automatically. For more information, see [Configure region](/guides/javascript#configure-region). For more examples, see the [examples in GitHub](https://github.com/axiomhq/axiom-js/tree/main/examples). --- # Configure dashboard elements Source: https://axiom.co/docs/dashboard-elements/configure When you create a chart, click to access the following options. ## Values [#values] Specify how to treat missing or undefined values: * **Auto:** This option automatically decides the best way to represent missing or undefined values in the data series based on the chart type and the rest of the data. * **Ignore:** This option ignores any missing or undefined values in the data series. This means that the chart only displays the known, defined values. * **Join adjacent values:** This option connects adjacent data points in the data series, effectively filling in any gaps caused by missing values. The benefit of joining adjacent values is that it can provide a smoother, more continuous visualization of your data. * **Fill with zeros:** This option replaces any missing or undefined values in the data series with zero. This can be useful if you want to emphasize that the data is missing or undefined, as it causes a drop to zero in your chart. ## Variant [#variant] Specify the chart type. **Area:** An area chart displays the area between the data line and the axes, often filled with a color or pattern. Stacked charts provide the capability to design and implement intricate query dashboards while integrating advanced visualizations, enriching your logging experience over time. Area chart **Bars:** A bar chart represents data in rectangular bars. The length of each bar is proportional to the value it represents. Bar charts can be used to compare discrete quantities, or when you have categorical data. Bar chart **Line:** A line chart connects individual data points into a continuous line, which is useful for showing logs over time. Line charts are often used for time series data. Line chart ## Y-Axis [#y-axis] Specify the scale of the vertical axis. **Linear:** A linear scale maintains a consistent scale where equal distances represent equal changes in value. This is the most common scale type and is useful for most types of data. Linear scale **Log:** A logarithmic (or log) scale represents values in terms of their order of magnitude. Each unit of distance on a log scale represents a tenfold increase in value. Log scales make it easy to see backend errors and compare values across a wide range. Log scale ## Annotations [#annotations] Specify the types of annotations to display in the chart: * Show all annotations * Hide all annotations * Selective determine the annotations types to display --- # Create dashboard elements Source: https://axiom.co/docs/dashboard-elements/create Dashboard elements are the different visual elements that you can include in your dashboard to display your data and other information. For example, you can track key metrics, logs, and traces, and monitor real-time data flow. You can create the following dashboard elements: * [Filter bar](/query-data/filters) * [Gauge](/dashboard-elements/gauge) * [Heatmap](/dashboard-elements/heatmap) * [Log stream](/dashboard-elements/log-stream) * [Monitor list](/dashboard-elements/monitor-list) * [Note](/dashboard-elements/note) * [Pie](/dashboard-elements/pie-chart) * [Scatter](/dashboard-elements/scatter-plot) * [Statistic](/dashboard-elements/statistic) * [Table](/dashboard-elements/table) * [Time series](/dashboard-elements/time-series) * [Top list](/dashboard-elements/top-list) * [Spacer](/dashboard-elements/spacer) To organize related dashboard elements into collapsible groups, [create dashboard sections](/dashboards/sections). ## Create dashboard elements [#create-dashboard-elements] 1. [Create a dashboard](/dashboards/create) or open an existing dashboard. 2. Click **Edit dashboard**. 3. Click **Add element** in the top right corner. 4. Choose the dashboard element from the list. 5. For charts, select one of the following: * Click **Builder** to create your chart using a [visual query builder](#create-chart-using-visual-query-builder). * Click **APL** to create your chart using the Axiom Processing Language (APL). Create a chart in the same way you create a chart in the [Editor of the Query tab](/query-data/query-editor). 6. Optional: [Configure chart options](/dashboard-elements/configure). 7. Optional: Set a custom time range that’s different from the dashboard’s time range. 8. Click **Save**. The new element appears in your dashboard. At the bottom, click **Save** to save your changes to the dashboard. ## Create chart using visual query builder [#create-chart-using-visual-query-builder] Use the query builder to create or edit queries for the selected dataset: Query builder This component is a visual query builder that eases the process of building visualizations and segments of your data. This guide walks you through the individual sections of the query builder. ### Time range [#time-range] Every query has a start and end time and the time range component allows quick selection of common time ranges as well as the ability to input specific start and end timestamps: Time range * Use the **Quick Range** items to quickly select popular ranges * Use the **Custom Start/End Date** inputs to select specific times * Use the **Resolution** items to choose between various time bucket resolutions ### Against [#against] When a time series visualization is selected, such as `count`, the **Against** menu is enabled and it’s possible to select a historical time to compare the results of your time range too. For example, to compare the last hour’s average response time to the same time yesterday, select `1 hr` in the time range menu, and then select `-1D` from the **Against** menu: Time range against menu The results look like this: Time range against chart The dotted line represents results from the base date, and the totals table includes the comparative totals. When you add `field` to the `group by` clause, the **time range against** values are attached to each `events`. Time range against chart ### Visualizations [#visualizations] Axiom provides powerful visualizations that display the output of running aggregate functions across your dataset. The Visualization menu allows you to add these visualizations and, where required, input their arguments: Visualizations menu You can select a visualization to add it to the query. If a visualization requires an argument (such as the field and/or other parameters), the menu allows you to select eligible fields and input those arguments. Press Enter to complete the addition. Click Visualization in the query builder to edit it at any time. [Learn about supported visualizations](/query-data/visualizations) ### Filters [#filters] Use the filter menu to attach filter clauses to your search. Axiom supports AND/OR operators at the top-level as well as one level deep. This means you can create filters that would read as `status == 200 AND (method == get OR method == head) AND (user-agent contains Mozilla or user-agent contains Webkit)`. Filters are divided up by the field type they operate on, but some may apply to more than one field type. #### List of filters [#list-of-filters] *String Fields* * `==` * `!=` * `exists` * `not-exists` * `starts-with` * `not-starts-with` * `ends-with` * `not-ends-with` * `contains` * `not-contains` * `regexp` * `not-regexp` *Number Fields* * `==` * `!=` * `exists` * `not-exists` * `>` * `>=` * `<` * `<=` *Boolean Fields* * `==` * `!=` * `exists` * `not-exists` *Array Fields* * `contains` * `not-contains` * `exists` * `not-exists` ### Group by (segmentation) [#group-by-segmentation] When visualizing data, it can be useful to segment data into specific groups to more clearly understand how the data behaves. The Group By component enables you to add one or more fields to group events by: Group by ### Other options [#other-options] #### Order [#order] By default, Axiom automatically chooses the best ordering for results. However, you can manually set the desired order through this menu. #### Limit [#limit] By default, Axiom chooses a reasonable limit for the query that has been passed in. However, you can control that limit manually through this component. ## Change element’s position [#change-elements-position] To change element’s position on the dashboard, drag the title bar of the chart.