Endpoints
All endpoints live on the Ingestion API base URLhttps://moda-ingest.modas.workers.dev and require your API key as a bearer token:
claude, codex, or cursor:
The 5 MB request body limit applies to every route (413 when exceeded).
Claude Code
Claude Code exports its telemetry over standard OpenTelemetry environment variables. Set them in your shell, or in theenv block of ~/.claude/settings.json so they apply to every session.
1
Configure the exporter
Without
OTEL_LOG_USER_PROMPTS=1, Claude Code sends only the prompt length — not the prompt text — so prompt events are stored without text. The variable controls what the agent emits; the ingestion service separately caps and redacts what it stores (see What is stored).2
Run a Claude Code session
Start Claude Code in the same environment and use it normally. Events are exported in batches while the session runs.
3
Verify ingestion
You can check your key and endpoint independently of the agent by posting an empty envelope:Successful OTLP exports receive A
200 with an empty partial-success body:401 response means the Authorization value (set through OTEL_EXPORTER_OTLP_HEADERS) is missing or carries an invalid key.claude_code. prefix is optional — short names are accepted):
Codex and Cursor
If you run Codex or Cursor with an OTLP exporter, point it at the matching provider path. What Moda needs from the exporter is the endpoint URL and theAuthorization header; for exporters configured through the standard OTLP environment variables, that is the same set as Claude Code with claude swapped for codex or cursor and no CLAUDE_CODE_ENABLE_TELEMETRY. A minimal logs-only configuration:
Hook events
The hooks routes accept plain JSON — a single event object or an array — so hook scripts wired into an agent’s hook system (for example Claude Code hooks) can report lifecycle events with a simple HTTP POST. Any process holding an API key can post them.hook is required on Claude payloads; a missing timestamp defaults to the receive time. Codex and Cursor hook payloads must carry a parseable timestamp (ISO 8601 string, Unix seconds, or Unix milliseconds) — payloads without one are counted in malformed and skipped, never failing the batch.
Recognized hook names:
Recognized optional fields include
session_id, cwd, repo, branch, git_commit, tool_name, tool_use_id, command, tool_input, tool_output, success, duration_ms, error ({type, message}), user_prompt, approval ({decision, source}), mcp_server, mcp_tool, skill_name, skill_scope, file_path, change_type, model, user_id, and user_email. Codex and Cursor payloads additionally accept conversation_id, sandbox_policy, subagent ({id, type}), and compaction ({input_tokens, output_tokens}). Unknown keys are preserved on the stored event.
What is stored and what is not
The ingestion service applies fixed caps and redaction to coding-agent events:
Secret redaction masks structured secret shapes — env-style assignments, header values, and explicit
key: value pairs — without touching ordinary prose. Unknown event and hook names are never dropped; they are stored with their attributes preserved.
Responses and errors
Always send a stable
timestamp on hook payloads, and reuse the same one when you retry a delivery. A Claude hook payload without a timestamp is stamped at receive time, so two deliveries of the same payload are recorded as separate events.
Next steps
- OpenTelemetry — the general-purpose trace endpoint for your application’s own LLM calls.
- Ingestion overview — authentication, limits, and the full endpoint inventory.
- Reliability — retry semantics and error envelopes.
- CLI overview — query captured data from the terminal.