Skip to main content
An axiom drain posts to one Axiom dataset’s ingest endpoint. Each record becomes one event with _time, level, message, and the whole Lua record under lua — which Axiom flattens at ingest, so lua.eventName and lua.attributes.* are queryable exactly as the event schema spells them.
Vendor destinations are opened per deployment. Where axiom is not open yet, a create answers 422 DRAIN_TYPE_UNAVAILABLE and the message names the types that are. It may not be enabled on your deployment yet.
Before you begin
  • An Axiom dataset.
  • An API token with ingest permission on it.

What to enter

The endpoint must name the dataset. https://api.axiom.co/v1/ingest/agent-logs is accepted; https://api.axiom.co alone is refused at create time with 422 DRAIN_VALIDATION_FAILED and field: "endpoint", because there is no dataset to ingest into. The dataset is public configuration, not a credential, so it stays in the stored endpoint and is visible on a read of the drain.
In CI:
The host must end in .axiom.co. That is a suffix rule, so api.eu.axiom.co is admitted and evil-axiom.co is not — the leading dot is what stops a lookalike domain matching. Anything else answers 422 DRAIN_ENDPOINT_NOT_ALLOWED. The last path segment may contain letters, digits, and . _ ~ % = + - only; anything else is refused rather than interpolated.

How ownership verification works

A vendor preset is reachability-checked, not ownership-verified. lua drains verify posts one batch holding a single lua.drain.test record, and any 2xx from the ingest endpoint is accepted. It proves the dataset exists and the token can write to it. It does not prove you own it. Only a generic HTTPS drain is ownership-verified by a token echo, and only an object-storage drain proves ownership by writing into a bucket.
A 401 means the token is wrong or lacks ingest permission; a 404 usually means the dataset in the URL does not exist. Verification is limited to 5 attempts per drain per hour. Axiom deliveries are not signed.

What arrives

A JSON array of events:
_time is the one reserved field, and sending it is what makes a replayed backlog readable: without it Axiom stamps ingestion time, and a batch delivered after a pause would all land at the same instant. A timestamp that does not parse is passed through untouched rather than replaced with “now” — Lua does not assert a time it never measured. level and message are not reserved, but they are what Axiom’s own dashboards look for.

Useful queries

Caps

A record over 256 KiB has its body cut and suffixed ... [truncated by lua] rather than being dropped.
The 448 KiB batch cap is roughly half what the other vendor presets use, and deliberately so: an Axiom event carries the body twice — once as message, once inside the nested record — so a full batch encodes to about 1.9× the bytes the cap was checked against. Halving the cap is what keeps a full batch inside a 1 MiB request.

Prefer OTLP? Use an otlp drain

Axiom accepts OTLP directly, and an otlp drain reaches it with no preset of its own: point it at Axiom’s OTLP logs endpoint and add X-Axiom-Dataset as a drain header.
The trade-off is the one on OpenTelemetry: OTLP gives you resource attributes promoted onto every record and a standard wire format, and it gives up the flat lua.* shape the native preset produces.

Test the token with curl

200 means accepted; the event shows up in the dataset within a few seconds. Then:

If it isn’t working

The URL does not end in a dataset. It must be the full ingest URL: https://api.axiom.co/v1/ingest/<dataset>.
The host does not end in .axiom.co. A self-hosted proxy in front of Axiom is not accepted by this type — use a generic HTTPS drain for that, which is signed as well.
That is ingestion time, which means _time was not read. Lua always sends it, so check for an ingest transform in Axiom that overwrites it.
The stored value must read Bearer <token>, prefix included — the header is sent verbatim. Re-enter it with lua drains update <id> --header Authorization.

Next steps

Event schema

What every field under lua means.

OpenTelemetry

The OTLP alternative, and what it trades.

Protecting your destination

What verification does and does not prove.

lua drains

Every verb and flag.