DeepTracer
API Reference

Ingestion API

Full reference for the DeepTracer ingestion endpoints — logs, errors, traces, LLM usage, and Vercel log drains.

Base URL: https://ingest.deeptracer.dev

All /ingest/* endpoints require an API key in the Authorization header. See Authentication for details.

The API uses snake_case for all field names (e.g., trace_id, error_message). The JavaScript SDK accepts camelCase and converts automatically. If you're calling the API directly with curl, Python, Go, etc., use snake_case.

POST /ingest/logs

Send a batch of log entries. You can send between 1 and 1,000 logs per request.

curl -X POST https://ingest.deeptracer.dev/ingest/logs \
  -H "Authorization: Bearer dt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "service": "my-app",
    "environment": "production",
    "logs": [
      {
        "level": "info",
        "message": "User signed up",
        "metadata": { "userId": "u_123", "plan": "pro" }
      },
      {
        "level": "error",
        "message": "Payment failed",
        "metadata": { "orderId": "ord_456", "reason": "card_declined" }
      }
    ]
  }'

Response 200 OK:

{ "ok": true, "count": 2 }

Fields

FieldTypeRequiredDefaultDescription
servicestringno"unknown"Service name (e.g., "web", "api")
environmentstringno"production"Environment (e.g., "staging", "development")
releasestringno--Release identifier, max 128 chars
logsarrayyes--Array of log entries (1-1000)
logs[].levelstringyes--"debug", "info", "warn", or "error"
logs[].messagestringyes--Log message
logs[].timestampstringnonowISO 8601 timestamp
logs[].metadataobjectno--Arbitrary key-value data
logs[].trace_idstringno--Trace ID for correlation
logs[].span_idstringno--Span ID for correlation
logs[].request_idstringno--Request ID
logs[].contextstringno--Logger context name
logs[].releasestringno--Per-entry release override, max 128 chars

POST /ingest/errors

Report a single error with stack trace and optional context. DeepTracer generates a fingerprint to group identical errors together.

curl -X POST https://ingest.deeptracer.dev/ingest/errors \
  -H "Authorization: Bearer dt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "service": "my-app",
    "environment": "production",
    "error_message": "Cannot read properties of undefined (reading '\''id'\'')",
    "stack_trace": "TypeError: Cannot read properties of undefined\n    at getUser (/app/src/users.ts:42:15)\n    at handler (/app/src/api/route.ts:10:3)",
    "severity": "high",
    "context": { "userId": "u_123", "route": "/api/users" }
  }'

Response 200 OK:

{ "ok": true, "fingerprint": "a1b2c3d4e5f6..." }

The fingerprint is a SHA-256 hash used to group identical errors. Errors with the same fingerprint show up as a single error group in the dashboard.

Fields

FieldTypeRequiredDefaultDescription
servicestringno"unknown"Service name
environmentstringno"production"Environment
error_messagestringyes--Error message text
stack_tracestringyes--Full stack trace
severitystringno"medium""low", "medium", "high", or "critical"
contextobjectno--Arbitrary context data
trace_idstringno--Trace ID for correlation
user_idstringno--User ID who triggered the error
releasestringno--Release identifier, max 128 chars
breadcrumbsarrayno--Recent actions leading to the error
breadcrumbs[].typestringyes--Breadcrumb type (e.g., "http", "ui", "navigation")
breadcrumbs[].messagestringyes--What happened
breadcrumbs[].timestampstringyes--ISO 8601 timestamp

POST /ingest/traces

Send a single distributed trace span. Group multiple spans into a trace using the same trace_id.

curl -X POST https://ingest.deeptracer.dev/ingest/traces \
  -H "Authorization: Bearer dt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "service": "my-app",
    "environment": "production",
    "trace_id": "abc123def456",
    "span_id": "span_001",
    "parent_span_id": "",
    "operation": "GET /api/users",
    "start_time": "2026-02-23T00:00:00.000Z",
    "duration_ms": 145,
    "status": "ok",
    "metadata": { "http.status_code": 200 }
  }'

Response 200 OK:

{ "ok": true }

Fields

FieldTypeRequiredDefaultDescription
servicestringno"unknown"Service name
environmentstringno"production"Environment
trace_idstringyes--Trace ID (groups spans into a trace)
span_idstringyes--Unique span identifier
parent_span_idstringno""Parent span ID (empty for root spans)
operationstringyes--Operation name (e.g., "GET /api/users")
start_timestringyes--ISO 8601 start timestamp
duration_msnumberyes--Duration in milliseconds (>= 0, rounded to integer)
statusstringno"ok""ok" or "error"
metadataobjectno--Arbitrary span attributes
releasestringno--Release identifier, max 128 chars

POST /ingest/llm

Report LLM/AI model usage for cost tracking and performance monitoring.

curl -X POST https://ingest.deeptracer.dev/ingest/llm \
  -H "Authorization: Bearer dt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "service": "my-app",
    "environment": "production",
    "model": "gpt-4o",
    "provider": "openai",
    "operation": "chat.completion",
    "input_tokens": 1250,
    "output_tokens": 340,
    "cost_usd": 0.0089,
    "latency_ms": 2100,
    "metadata": { "feature": "support-chat" }
  }'

Response 200 OK:

{ "ok": true }

Fields

FieldTypeRequiredDefaultDescription
servicestringno"unknown"Service name
environmentstringno"production"Environment
modelstringyes--Model identifier (e.g., "gpt-4o", "claude-sonnet-4-5-20250514")
providerstringyes--Provider name (e.g., "openai", "anthropic")
operationstringyes--Operation type (e.g., "chat.completion", "embedding")
input_tokensnumberyes--Input/prompt token count (>= 0, rounded to integer)
output_tokensnumberyes--Output/completion token count (>= 0, rounded to integer)
cost_usdnumberno0Estimated cost in USD
latency_msnumberyes--Request latency in milliseconds (>= 0, rounded to integer)
metadataobjectno--Arbitrary metadata
releasestringno--Release identifier, max 128 chars

POST /ingest/drain

Vercel Log Drain webhook endpoint. Receives logs forwarded by Vercel's log drain integration.

This endpoint is configured in your Vercel project settings, not called directly. It accepts the standard Vercel log drain payload format (an array of log entries).

For setup instructions, see the Vercel integration guide.


GET /health

Liveness check. No authentication required.

curl https://ingest.deeptracer.dev/health

Response 200 OK:

{ "status": "ok", "timestamp": "2026-02-23T00:00:00.000Z" }

GET /health/ready

Readiness check with dependency status. No authentication required. Returns the health status of ClickHouse, Redis, and PostgreSQL connections.

curl https://ingest.deeptracer.dev/health/ready

Error responses

All endpoints return JSON error responses with appropriate HTTP status codes.

401 Unauthorized — Missing or invalid API key:

{ "error": "Missing or invalid API key" }

400 Bad Request — Validation failed. The response includes Zod error details telling you exactly which fields failed:

{
  "success": false,
  "error": {
    "issues": [
      {
        "code": "invalid_type",
        "expected": "string",
        "received": "undefined",
        "path": ["error_message"],
        "message": "Required"
      }
    ],
    "name": "ZodError"
  }
}

403 Forbidden — Browser request from an origin not in your allowed list:

{ "error": "Origin not allowed" }

429 Too Many Requests — Rate limit exceeded. See Rate Limits for details:

{ "error": "Rate limit exceeded" }

Field naming convention

SDK (camelCase)API (snake_case)
errorMessageerror_message
stackTracestack_trace
traceIdtrace_id
spanIdspan_id
parentSpanIdparent_span_id
startTimestart_time
durationMsduration_ms
inputTokensinput_tokens
outputTokensoutput_tokens
costUsdcost_usd
latencyMslatency_ms
userIduser_id
requestIdrequest_id

If you're using the JavaScript SDK, you write camelCase and the SDK translates automatically. If you're hitting the API directly, use snake_case.

On this page