How ingest works
- You send batches over HTTPS to
logs.uptimeeye.comwith an ingest key. - The key resolves to your organization; lines are stored in your organization's isolated tenant.
- Each line becomes an entry with a message, a time and any number of fields. No schema, no index configuration.
- About a second later the entry is searchable on the Logs page; Live tail shows it after ~6 s.
Ingest keys
Create keys under API Keys → New API Key with type “Log ingest”. They start with ue_ingest_, are shown once, and can only write logs — a management key (ue_live_) is refused by the ingest endpoints, and an ingest key cannot read or change anything in your account.
Send the key as a bearer token, or as HTTP basic auth for tools that only know user/password (any user name, the key as password):
Authorization: Bearer ue_ingest_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# or
Authorization: Basic base64("key:ue_ingest_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")Endpoints
Base URL https://logs.uptimeeye.com. All endpoints accept gzip-compressed bodies (Content-Encoding: gzip) up to 16 MiB uncompressed.
| Endpoint | Format | Typical senders |
|---|---|---|
| POST /v1/ingest/jsonline | One JSON object per line (NDJSON) | curl, scripts, Fluent Bit http, logging libraries |
| POST /v1/ingest/text | Plain text, one entry per line; time and level detected, stack traces folded | log files, docker logs, Spring/log4j output |
| POST /v1/ingest/elasticsearch/_bulk | Elasticsearch bulk API (GET / and /_license answer the handshake) | Vector, Filebeat, Fluent Bit es |
| POST /v1/ingest/otlp/v1/logs | OTLP/HTTP logs (protobuf) | OpenTelemetry Collector and SDKs, Serilog |
| POST /v1/ingest/loki/api/v1/push | Loki push (JSON or snappy protobuf); labels become stream fields | Promtail, Grafana Alloy, Docker Loki driver |
Message, time and fields
An entry is a flat set of string fields. Three names are special; everything else is yours:
| Field | Meaning | Default |
|---|---|---|
| _msg | The message shown in the list and searched by word queries | the key named in _msg_field, else empty |
| _time | Event time, RFC 3339 / ISO 8601 or Unix seconds/millis/nanos | the key named in _time_field, else arrival time |
| _stream | Stream labels, built from _stream_fields | service,host if present |
Nested JSON is flattened to dotted names: {"http":{"status":500}} becomes the field http.status. Arrays are stored as JSON strings. Field names are case-sensitive.
Good field hygiene
- Always send
serviceandenv— they drive the fields panel, the setup examples and most filters. - Put identifiers (
order_id,user_id,trace_id) into fields, not into the message text. - Keep one name per concept across services (
duration_ms, notlatencyhere andtookthere). - Log levels as lowercase words (
info,warn,error) solevel:errorworks everywhere.
Stream fields
A stream is the set of entries sharing the same values of the stream fields — think {service="api", env="prod"}. Streams are stored together, so a filter on them (_stream:{...}, or simply a chip on a stream field) is the fastest way to narrow a search, and the fields panel lists stream fields first.
- Choose them per request with
_stream_fields=service,env(query arg orVL-Stream-Fieldsheader). Up to 6 fields; the default isservice,host. - Pick fields with few distinct values that you filter on constantly:
service,env,namespace,region,host. - Never use high-cardinality values (
request_id,podon a busy cluster,user_id) — every distinct combination is a separate stream.
Ingest options
Options are passed as query arguments on any endpoint, or as headers for agents that cannot set the URL. Query arguments win.
| Query arg | Header | Effect |
|---|---|---|
| _stream_fields | VL-Stream-Fields | comma-separated fields that form the stream (max 6) |
| _msg_field | VL-Msg-Field | which key holds the message (e.g. message, log, msg) |
| _time_field | VL-Time-Field | which key holds the timestamp (e.g. @timestamp, time, ts) |
| _ignore_fields | VL-Ignore-Fields | keys to drop before storing |
| _extra_fields | VL-Extra-Fields | constant fields to add, k1=v1,k2=v2 |
| _default_msg_value | VL-Default-Msg-Value | message to use when the entry has none |
The plain-text endpoint adds _time_source=ingest and _multiline=off, and treats every non-underscore query argument as a constant field.
Limits, quota, retention
| Limit | Value |
|---|---|
| Request body | 16 MiB uncompressed; gzip accepted |
| Stream fields | 6 per request |
| Monthly volume | per plan, measured in uncompressed bytes as received; shown on the Logs page |
| Retention | per plan; older entries are removed automatically and the search range is capped to it |
| Over quota | 429 Too Many Requests with a Retry-After header until the month rolls over; the batch that crosses the line is still accepted |
Response codes
| Status | Meaning | What to do |
|---|---|---|
| 200 | accepted (/text answers {"entries": N}) | — |
| 400 | malformed JSON, text without lines, or broken compression | fix the payload; the body names the first bad line |
| 401 | missing, malformed or unknown ingest key | check the Authorization header and that the key is of type Log ingest |
| 403 | the plan has no Logs, or the organization has no log tenant yet | upgrade, or create an ingest key first |
| 413 | body over 16 MiB | send smaller batches |
| 415 | unsupported Content-Encoding | use gzip or none |
| 429 | monthly quota exhausted | back off until Retry-After; agents retry on their own |
| 502 / 503 | storage or key lookup temporarily unavailable | retry with backoff; nothing was accepted |
Choose an integration
Verify
Open Logs, choose the 15m range and search service:=<your service>. If nothing shows up, check the agent's log for the HTTP status of its last request (see the table above), and the time: an agent that sends timestamps from a clock that is off by minutes puts lines outside the 15m window — try 24h.
Then continue with Searching logs.
FAQ
Can several services share one ingest key?
service field to tell them apart. Separate keys per environment or team make rotation easier.What happens if I revoke a key?
401 within about 30 seconds (the gateway caches key lookups briefly). Lines already accepted stay searchable.Are timestamps required?
_time (or the key named in _time_field) the arrival time is used. Send timestamps when you replay files or when agents batch for more than a few seconds.