Skip to main content
A betterstack drain posts to one Better Stack source’s ingesting host. Records arrive with dt as the timestamp, level as the severity, message as the log line, and the whole Lua record kept alongside as structured fields you can query and alert on. Before you begin
  • A Better Stack source of type HTTP. Its Connect page gives you two things you need: the ingesting host and the source token.

What to enter

Output
The ingesting host is specific to your source and to the region the source lives in — it is not a single shared endpoint, so copy it from the Connect page rather than guessing.
Better Stack deliveries are not signed. There is no X-Lua-Signature header and no signing secret; the Authorization header authenticates the sender. If you need a signature, use a generic HTTPS drain.

How ownership verification works

Better Stack uses a test post: one batch containing a single lua.drain.test record is sent to the ingesting host, and any 2xx is accepted.
A 401 means the token is wrong or is missing its Bearer prefix — the stored value is sent as the whole header value, so Bearer is part of what you enter. The drain stays in pending_verification and keeps buffering (for up to six hours) while you fix it. Verification is limited to 5 attempts per drain per hour.

What arrives

Each record becomes one entry in a JSON array:
The batch’s resource is not flattened into each entry, so an entry carries no organization id, agent id, or agent name — only the record. Group by lua.attributes["lua.primitive.name"] for a primitive and by lua.eventName for a kind of event.
If you need the agent or the environment on every record — one source receiving several agents, for example — send to an OpenTelemetry collector instead and promote the resource attributes there. The published collector config already copies service.name and the environment onto each record, and its exporter can forward to Better Stack.

Useful queries

Caps

Test the token with curl

Prove the host and the token before creating the drain. This sends exactly the shape a delivery has:
A 202 means accepted; the entry shows up in Live tail within a few seconds. A 401 means the token is wrong or the Bearer prefix is missing; a 404 usually means the ingesting host belongs to a different source or region. Then do the same through the real delivery path:

Alert on it

Better Stack alerts on a saved query. Three that are worth having from day one: The heartbeat is what makes the other two trustworthy: it arrives every five minutes while the drain is healthy, so its absence tells you the pipeline is down rather than that your agents went quiet. Delivery guarantees explains what it does and does not prove.

If it isn’t working

The stored header value is sent verbatim as Authorization. It must read Bearer <source token>, prefix included. Update it with lua drains update <id> --header Authorization and re-enter the whole value.
The ingesting host is per-source and per-region. Copy it from that source’s Connect page. A 3xx is treated as a failure and never followed, so a host that redirects has to be replaced with its final URL.
healthy means the ingesting host accepted the batch. Check that you are looking at the right source, and that the source’s retention and any archiving rule have not moved the data. lua drains deliveries <id> shows the status code and response excerpt for each recent batch.

Next steps

Event schema

What every field under lua means.

Delivery guarantees

Retry, drops, heartbeat, and health states.

Ship logs to your stack

Selectors, states, and quotas.

lua drains

Every verb and flag.