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.devAuthentication
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
| Method | Path | Signal | Response |
|---|---|---|---|
| GET | /health | — | 200 { status: "ok" } |
| POST | /v1/traces | Traces | 202 (accepted, async write) |
| POST | /v1/logs | Logs | 202 (accepted, async write) |
| POST | /v1/metrics | Metrics | 202 (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
| Attribute | Stored as |
|---|---|
| service.name | service column |
| deployment.environment | environment column |
| host.name | host_name column |
| k8s.pod.name | pod_name column |
| k8s.node.name | node_name column |
Span attributes extracted
| Attribute | Stored as |
|---|---|
| log.message / message / body | body column (the log text) |
| log.severity / level | severity column |
| http.status_code | status_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.