---
title: "Ingest OTLP logs (Bearer-authenticated)"
method: POST
path: "/v1/logs"
tags: ["Traces"]
---

# Ingest OTLP logs (Bearer-authenticated)

`POST /v1/logs`

## Request

- Base URL: `https://ping.lastping.dev`
- URL: `https://ping.lastping.dev/v1/logs`
- Auth: HTTP bearer

Accepts one OTLP `ExportLogsServiceRequest` (protobuf or its JSON
mapping) and enqueues the agent events it carries: Claude Code's
documented events (`user_prompt`, `assistant_response`,
`tool_result`, `tool_decision`, `api_request`, `api_error`), Codex's
documented events and Cursor's error events. A record whose `event.name` LastPing does
not keep is counted in `dropped` and discarded; the rest of the
request is kept. A record's own timestamp counts when it is within
seven days before, or an hour after, the moment ingest received it;
otherwise it counts at that moment. A redelivered record is stored
once.

**Content**: the monitor's `trace_content` applies. At `dropped`
(the default) prompt, response and tool content is removed; at
`redacted` it is stored with every secret-shaped value replaced by
`[REDACTED:<class>]`. Either way every value is redacted before
anything is queued. A change of `trace_content` reaches ingest
within 60 seconds.

**Auth**: exactly as `POST /v1/traces` (Bearer key scoped `ingest`,
`write` or `admin`; `lastping.monitor_id` names the monitor unless
the key is bound to one; 404 for a monitor outside the key's
project).

**Content-Type**: `application/x-protobuf` or `application/json`
(415 otherwise). `Content-Encoding: gzip` is accepted.

**Caps**: body ≤ 1 MiB decompressed (413 over); ≤ 500 log records per
request (400 over). Rate limit: 3,600 requests/hour/project, its own
bucket. Log records count against the project's daily span budget,
and against a daily log event cap inside it (default 200,000 per
UTC day).

**Durability**: 202 only after the enqueue succeeds; a queue failure
is 503, never a silent ack.

## Request body

- object: The OTLP JSON mapping of `ExportLogsServiceRequest`.

## Response `202`

Accepted and enqueued.

- object
  - `accepted` integer, required: Data points or log records enqueued from this request.
  - `dropped` integer, required: Data points or log records of this request that LastPing does not keep (an unknown metric family or event, a cumulative point, a point with no usable value) and discarded. When a request kept nothing, the monitor's ingest diagnostics say why.

## Other responses

- `400`: Malformed OTLP payload, more than 500 log records, or a missing `lastping.monitor_id`, or one that disagrees with the monitor the key is bound to.
- `401`: Missing, unknown, revoked or expired API key.
- `403`: The API key's scope is `read`.
- `404`: `lastping.monitor_id` does not name a check in the key's project. No existence oracle.
- `413`: Decompressed body exceeds 1 MiB.
- `415`: Content-Type is neither `application/x-protobuf` nor `application/json`.
- `429`: The logs rate cap for this project (3,600 requests/hour, its own bucket) is exceeded, with `Retry-After: 60`. Or the project's daily span budget, which log records count against, is used up: `code: "SPAN_BUDGET_EXCEEDED"`. Or today's log event cap inside it (default 200,000 per UTC day) is used up: `code: "LOG_EVENT_BUDGET_EXCEEDED"`. Both budget refusals carry a `Retry-After` to 00:00 UTC. Or LastPing is already reading as many OTLP exports as it takes at once: `code: "OTLP_BUSY"`, `Retry-After: 5`.
- `503`: Ingestion is unavailable on this deployment, the queue could not accept the message, or a budget could not be read. Retry.

---

[API](https://skmtc.dev/lastping/apis/lastping-management-api.md) · [All operations](https://skmtc.dev/lastping/apis/lastping-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lastping/apis/lastping-management-api/revisions/bbc6eda91c46?raw)
