Dashboard Get started

Ingest API (OTLP)

The ingest gateway accepts standard OpenTelemetry Protocol (OTLP) JSON payloads. Any OTel-compatible SDK or library works out of the box.

Base URL

text
https://la-ingest-gateway.lightarch.workers.dev

Authentication

Include your DSN in the x-la-dsn header on every request:

bash
curl -X POST https://la-ingest-gateway.lightarch.workers.dev/v1/traces \
  -H "x-la-dsn: la_live_YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{ ... OTLP payload ... }'
Keep your DSN secret. If exposed, rotate it immediately in Settings → DSN.

Endpoints

MethodPathSignalResponse
GET/health200 { status: "ok" }
POST/v1/tracesTraces202 (accepted, async write)
POST/v1/logsLogs202 (accepted, async write)
POST/v1/metricsMetrics202 (accepted, async write)

POST /v1/traces

Request body (OTLP JSON)
{
  "resourceSpans": [{
    "resource": {
      "attributes": [
        { "key": "service.name",           "value": { "stringValue": "my-service" } },
        { "key": "deployment.environment", "value": { "stringValue": "production" } },
        { "key": "host.name",              "value": { "stringValue": "ip-10-0-1-42" } }
      ]
    },
    "scopeSpans": [{
      "spans": [{
        "traceId":            "aabbccdd11223344556677889900aabb",
        "spanId":             "1122334455667788",
        "name":               "GET /api/users",
        "startTimeUnixNano":  "1716138000000000000",
        "endTimeUnixNano":    "1716138000142000000",
        "attributes": [
          { "key": "http.method",      "value": { "stringValue": "GET" } },
          { "key": "http.status_code", "value": { "intValue": 200 } },
          { "key": "log.message",      "value": { "stringValue": "Handled GET /api/users" } },
          { "key": "log.severity",     "value": { "stringValue": "INFO" } }
        ],
        "status": { "code": 1 }
      }]
    }]
  }]
}

Resource attributes extracted

AttributeStored as
service.nameservice column
deployment.environmentenvironment column
host.namehost_name column
k8s.pod.namepod_name column
k8s.node.namenode_name column

Span attributes extracted

AttributeStored as
log.message / message / bodybody column (the log text)
log.severity / levelseverity column
http.status_codestatus_code column

POST /v1/logs

Follows the OTel LogRecord format. The body.stringValue field becomes the body column.

Request body
{
  "resourceLogs": [{
    "resource": {
      "attributes": [
        { "key": "service.name", "value": { "stringValue": "my-service" } }
      ]
    },
    "scopeLogs": [{
      "logRecords": [{
        "timeUnixNano": "1716138000000000000",
        "severityNumber": 17,
        "severityText": "ERROR",
        "body": { "stringValue": "Payment failed: card declined" },
        "traceId": "aabbccdd11223344556677889900aabb",
        "spanId":  "1122334455667788",
        "attributes": [
          { "key": "order.id", "value": { "stringValue": "ord_abc123" } }
        ]
      }]
    }]
  }]
}

POST /v1/metrics

Histogram example
{
  "resourceMetrics": [{
    "resource": { "attributes": [
      { "key": "service.name", "value": { "stringValue": "my-service" } }
    ]},
    "scopeMetrics": [{
      "metrics": [{
        "name": "http.server.request.duration",
        "histogram": {
          "dataPoints": [{
            "timeUnixNano": "1716138000000000000",
            "count": 42,
            "sum": 4.2,
            "explicitBounds": [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0],
            "bucketCounts": [2, 3, 5, 8, 10, 6, 4, 2, 1, 1, 0],
            "attributes": [
              { "key": "http.method", "value": { "stringValue": "GET" } }
            ]
          }]
        }
      }]
    }]
  }]
}
p50 and p99 are computed from explicitBounds + bucketCountsat ingest time. Duration histograms in seconds are automatically converted to milliseconds.