Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mortemlabs.com/llms.txt

Use this file to discover all available pages before exploring further.

The batch endpoint is the main write path for agent trace data. Every time the SDK flushes its internal buffer — on a timer, when the buffer fills, or when mortem.close() is called — it serializes the queued trace and event objects, compresses them with gzip, and sends them here. You can call this endpoint directly if you are building your own instrumentation or sending traces from outside the SDK.
POST https://ingest.mortem.dev/v1/traces/batch

Request headers

HeaderValueRequired
AuthorizationBearer <MORTEM_API_KEY>Yes
Content-Typeapplication/jsonYes
Content-EncodinggzipWhen body is compressed
The SDK always sends gzip-compressed bodies and includes Content-Encoding: gzip. If you are calling the endpoint directly without compression, omit the Content-Encoding header and send plain JSON. Both are accepted.

Request body

The request body is a JSON object that matches TransportBatchPayload.
batchId
string
required
A unique identifier for this batch, used for idempotency and deduplication. The SDK generates a ULID for each flush. If you are calling the API directly, generate a ULID or UUID per request.
items
BufferBatchItem[]
required
An array of trace-and-events bundles to ingest. Each element must contain a full trace object and the array of events captured since the last flush. The array must contain at least one item.
agentId
string
The agent ID the batch belongs to. Include this when you also include verifyToken — it lets the ingest service match the token to the correct agent record. In all other cases the agent is identified by the API key alone and this field is ignored.
verifyToken
string
A one-time token sent on the first ever flush from a new agent. The dashboard generates this token during onboarding and uses it to confirm your agent is live and the API key is correctly configured. After the dashboard marks the agent as verified, you can remove the token from your environment — it is consumed and cannot be reused.

items[].trace

Each trace object is a complete snapshot of the trace’s current state at flush time. The ingest service upserts on id, so partial updates from intermediate flushes are safe — later flushes overwrite earlier ones for the same trace ID.
id
string
required
The trace’s unique identifier. The SDK generates a ULID when the session starts. This ID is stable across all flushes for the same session — it is the primary key used for upsert.
agentId
string
required
The agent that owns this trace. The ingest service overwrites this with the agent resolved from the API key, so the value you send is effectively ignored — but the field must be present and a non-empty string.
status
string
required
The trace’s current lifecycle state. One of "running", "completed", "errored", or "timeout". In-progress flushes use "running". The final flush from session.complete() or session.fail() sets this to "completed" or "errored" respectively.
startedAt
string
required
ISO 8601 datetime string for when the trace started. This is the timestamp of the mortem.startSession() call (or the startedAt value you passed in SessionOptions).
inputSummary
string
required
The human-readable description of what this agent run was attempting to do. This is the value you pass as inputSummary in SessionOptions and becomes the trace title in the dashboard.
endedAt
string
ISO 8601 datetime string for when the trace ended. null while the trace is still running.
durationMs
number
Wall-clock duration of the trace in milliseconds. null while still running.
outputSummary
string
The output summary written by session.complete(outputSummary). null if not yet set.
errorMessage
string
The error message written by session.fail(error). null unless the trace ended in an error.
tags
string[]
required
Labels attached to the trace. Pass an empty array if you did not specify tags in SessionOptions.
eventCount
number
required
Total number of events recorded on this trace so far.
totalTokens
number
required
Cumulative token count across all llm_call events on this trace.
totalCostUsd
string
required
Cumulative estimated LLM cost as a decimal string (for example "0.0042").
totalLamports
string
required
Cumulative lamports transferred across all solana_tx events, serialized as a decimal string because JSON cannot represent bigint natively.
solanaTxCount
number
required
Number of solana_tx events on this trace.
toolsCalled
string[]
required
Deduplicated list of tool names called on this trace via tool_call events.
anchorSignature
string
On-chain anchor signature if the trace was anchored. Reserved for future on-chain anchoring features. Pass null.
anchorSlot
string
Solana slot at which the trace was anchored, serialized as a decimal string. Reserved for future on-chain anchoring features. Pass null.
merkleProof
string
Merkle proof string for the trace hash. Reserved for future integrity verification features. Pass null.
traceHash
string
Deterministic hash of the trace content. Reserved for future integrity verification features. Pass null.
shareToken
string
Share token for the public trace URL if the trace has been shared from the dashboard. null if not shared.

items[].events

Each element in the events array represents a single instrumented step in the agent run. Pass an empty array when flushing a trace state update with no new events.
id
string
required
Unique identifier for this event. The SDK generates a ULID.
traceId
string
required
The ID of the trace this event belongs to. Must match items[].trace.id.
sequence
number
required
Monotonically increasing integer that determines the display order of events in the trace timeline. The SDK assigns sequence numbers from a per-session counter starting at 0.
type
string
required
The event category. One of "llm_call", "tool_call", "solana_tx", "x402_payment", "mcp_call", or "custom". The dashboard renders each type with a distinct icon and payload layout.
startedAt
string
required
ISO 8601 datetime string for when this event started.
payload
object
required
The event-specific payload object. The shape depends on type. See the event types reference for the full payload schema for each type.
status
string
required
The event’s terminal status. Use "ok" for success and "error" for failure.
parentEventId
string
The ID of the parent event, if this event is nested inside another. null for top-level events.
endedAt
string
ISO 8601 datetime string for when this event completed. null for in-progress events.
durationMs
number
Duration of the event in milliseconds. null for in-progress events.
errorMessage
string
Error message if the event failed. null on success.
payloadEncrypted
boolean
required
true if the payload was encrypted with MORTEM_MASTER_KEY before transmission. The dashboard decrypts it transparently when you have the key configured.

Response

On success the endpoint returns 202 Accepted with the ID of the first trace in the batch.
{ "traceId": "01J8XKZP4N0000000000000000" }

Example

curl -X POST https://ingest.mortem.dev/v1/traces/batch \
  -H "Authorization: Bearer $MORTEM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "batchId": "01J8XKZP4N0000000000000001",
    "items": [
      {
        "trace": {
          "id": "01J8XKZP4N0000000000000000",
          "agentId": "01J8AGENT00000000000000000",
          "status": "running",
          "startedAt": "2025-01-15T10:30:00.000Z",
          "endedAt": null,
          "durationMs": null,
          "inputSummary": "Evaluate whether to swap 1 SOL for JUP",
          "outputSummary": null,
          "errorMessage": null,
          "eventCount": 1,
          "totalTokens": 312,
          "totalCostUsd": "0.0004",
          "totalLamports": "0",
          "solanaTxCount": 0,
          "toolsCalled": [],
          "anchorSignature": null,
          "anchorSlot": null,
          "merkleProof": null,
          "traceHash": null,
          "shareToken": null,
          "tags": ["swap", "devnet"]
        },
        "events": [
          {
            "id": "01J8XKZP4N0000000000000002",
            "traceId": "01J8XKZP4N0000000000000000",
            "parentEventId": null,
            "sequence": 0,
            "type": "llm_call",
            "startedAt": "2025-01-15T10:30:00.100Z",
            "endedAt": "2025-01-15T10:30:01.400Z",
            "durationMs": 1300,
            "payload": {
              "provider": "openai",
              "model": "gpt-4o-mini",
              "input": {
                "messages": [
                  { "role": "user", "content": "Should I swap 1 SOL for JUP right now?" }
                ]
              },
              "output": {
                "content": "Based on current market conditions...",
                "finishReason": "stop"
              },
              "usage": { "inputTokens": 24, "outputTokens": 288, "totalTokens": 312 },
              "costUsd": 0.0004,
              "streamed": false
            },
            "payloadEncrypted": false,
            "status": "ok",
            "errorMessage": null
          }
        ]
      }
    ]
  }'