ALTARED Telemetry API
Version v1 · versioned, additive changes only
This service has no public sign-up and no public sign-in link. Account creation is disabled at the identity layer, so a new account cannot be registered from the browser or by calling the auth API directly. Nothing on the public pages links to the console.
There are exactly three ways to reach the data:
https://telemetry.altared.io/auth by typing that address directly. Sessions are role-gated: an account with no role granted sees no data.telemetry:read / read-all). See Reading collected telemetry.Reporting applications never need console access: they hold a write-only credential and only call the ingestion endpoints.
Unauthorized requests are rejected, not silently accepted:
# No credential (telemetry, heartbeat, verify, events, fleet)
curl -i -X POST https://telemetry.altared.io/api/public/v1/telemetry -d '{"event":"test"}'
→ 401 { "ok": false, "error": { "code": "invalid_credential", ... } }
# Unknown, revoked or expired credential
curl -i -X POST https://telemetry.altared.io/api/public/v1/telemetry -H "Authorization: Bearer alt_unknown" -d '{"event":"test"}'
→ 401 { "ok": false, "error": { "code": "invalid_credential", ... } }
# Write-only credential calling the read API
curl -i "https://telemetry.altared.io/api/public/v1/events?limit=1" -H "Authorization: Bearer $WRITE_ONLY_KEY"
→ 403 { "ok": false, "error": { "code": "permission_denied", ... } }
# Creating an account is refused by the identity layer
→ 422 { "error_code": "signup_disabled", "msg": "Signups not allowed for this instance" }
# Only the liveness check is open (it validates nothing and returns no data)
curl -i https://telemetry.altared.io/api/public/v1/status
→ 200Register an application in the console, copy its API key once, then send your first event. Base URL for this deployment:
https://telemetry.altared.io/api/public/v1
curl -X POST https://telemetry.altared.io/api/public/v1/telemetry \
-H "Authorization: Bearer $TELEMETRY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"event": "payment.completed",
"severity": "info",
"message": "Invoice 4021 paid",
"tags": ["billing"],
"data": { "invoice_id": "4021", "amount_cents": 12900 }
}'Every request carries the application's own API key, either as Authorization: Bearer <key> or x-api-key: <key>. Keys are stored only as SHA-256 hashes, are shown exactly once, and carry least-privilege scopes:
There is no global master key. Revoking one application's credential never affects another.
Each application is fully independent: its own identity, credentials, environment and data. This service never connects to an application database, and an application never connects to the telemetry database.
GET https://telemetry.altared.io/api/public/v1/application/status
Authorization: Bearer <key>
200 OK
{
"application": { "id": "…", "name": "Billing Service", "environment": "production", "status": "healthy" },
"last_telemetry_at": "2026-09-16T09:41:12.004Z",
"last_heartbeat_at": "2026-09-16T09:44:02.551Z",
"request_id": "req_…"
}POST /api/public/v1/telemetry — requires telemetry:write.
{
"event": "database.error", // required, 1–120 chars
"severity": "error", // debug | info | warning | error | critical (default info)
"message": "connection pool exhausted", // optional, ≤1000 chars
"occurred_at": "2026-09-16T09:40:00Z", // optional client timestamp
"tags": ["db", "pool"], // optional, ≤20 tags
"idempotency_key": "…", // optional; header Idempotency-Key also accepted
"data": { "pool": "primary", "waiting": 24 } // optional JSON object
}The server owns all security-sensitive metadata — application ID, environment, received timestamp, request ID, credential ID and processing status are derived from the authenticated credential, never from the request body.
202 Accepted
x-request-id: req_9f21…
x-telemetry-api-version: v1
x-ratelimit-limit: 600
x-ratelimit-remaining: 594
{ "ok": true, "accepted": 1, "duplicates": 0, "ids": ["…"], "request_id": "req_9f21…" }Batching: send up to 100 events in one request by posting { "events": [ … ] } with the same event shape in each element. The response reports how many were accepted and how many were duplicates.
curl -X POST https://telemetry.altared.io/api/public/v1/telemetry \
-H "Authorization: Bearer $TELEMETRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "events": [
{ "event": "service.started", "severity": "info" },
{ "event": "user.login", "severity": "info", "data": { "method": "google" } }
] }'GET /api/public/v1/verify is the only endpoint that proves a key works. It authenticates, reports the application identity, scopes and limits, and writes nothing to telemetry — so an application can self-check at startup without polluting data. GET /status requires no key and is never proof of a working credential.
curl https://telemetry.altared.io/api/public/v1/verify \
-H "Authorization: Bearer $TELEMETRY_API_KEY"
200 OK
{
"verified": true,
"application": { "id": "…", "name": "Billing Service", "environment": "production" },
"scopes": ["telemetry:write", "heartbeat:write"],
"limits": { "max_payload_bytes": 65536, "max_batch_events": 100, "requests_per_minute": 600 },
"request_id": "req_…"
}GET /api/public/v1/events returns collected events in stable order with keyset pagination, so a consumer can resume exactly where it stopped and never skip or repeat a row. A credential with telemetry:read reads only its own application; telemetry:read:all (issued to the upstream analytics hub) reads every reporting application.
curl "https://telemetry.altared.io/api/public/v1/events?limit=200&cursor=$CURSOR" \
-H "Authorization: Bearer $TELEMETRY_READ_KEY"
200 OK
{
"ok": true,
"count": 200,
"has_more": true,
"next_cursor": "MjAyNi0…", // persist this, send it back next poll
"scope": "all_applications",
"events": [
{
"id": "…",
"application": { "id": "…", "name": "Billing Service", "slug": "billing-service" },
"environment": "production",
"event": "database.error",
"severity": "error",
"received_at": "2026-09-18T11:04:02.118Z",
"occurred_at": "2026-09-18T11:04:01.902Z",
"request_id": "req_…",
"idempotency_key": null,
"tags": [],
"data": { }
}
],
"request_id": "req_…"
}Optional filters: since (ISO timestamp), environment, severity, application_id (ignored unless the credential holds telemetry:read:all). limit is 1–500, default 100. Poll on an interval, persist next_cursor durably, and keep requesting while has_more is true.
GET /api/public/v1/fleet requires telemetry:read:all and returns every reporting application with its live status, last heartbeat, last event and seconds_since_last_signal — enough to render fleet health without reading events.
POST /api/public/v1/heartbeat — requires heartbeat:write. Send on a fixed interval (30–60s is typical); a missing heartbeat is what marks an application offline.
curl -X POST https://telemetry.altared.io/api/public/v1/heartbeat \
-H "Authorization: Bearer $TELEMETRY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "ok", "version": "1.4.2", "metadata": { "host": "worker-3" } }'GET /api/public/v1/status is an unauthenticated liveness probe for the ingestion API. It never exposes application data.
{
"ok": true,
"service": "altared-telemetry",
"version": "v1",
"status": "healthy",
"authenticated": false,
"note": "This probe does not authenticate. Use GET /api/public/v1/verify to prove a credential works.",
"request_id": "req_..."
}Errors are structured, human-readable and always carry a request ID. Stack traces are never returned.
401 invalid_credential The API key is missing, unknown or not active.
403 permission_denied The credential lacks the required scope.
403 application_disabled The application is disabled in ALTARED Telemetry.
429 rate_limit_exceeded Too many requests for this credential.
413 payload_too_large Payload exceeds 65536 bytes.
400 invalid_payload Payload failed schema validation (stored as a rejected event).
405 method_not_allowed Wrong HTTP method for this endpoint.
503 service_unavailable Telemetry database write failed — retry with backoff.
{ "error": { "code": "invalid_payload", "message": "…", "request_id": "req_…" } }Malformed telemetry is never silently discarded: it is stored as a rejected event and logged.
600 requests per minute per credential by default, plus a 65,536-byte payload limit. Exceeding either returns a structured error — treat both as retryable with backoff, never as a fatal application error.
Telemetry observes your application; it must never control it. Client requirements:
async function sendWithBackoff(payload, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
const res = await postTelemetry(payload); // 3s timeout inside
if (res.ok || res.status < 500) return; // 4xx is not retryable
} catch { /* ignore */ }
await new Promise((r) => setTimeout(r, 2 ** i * 250 + Math.random() * 100));
}
// give up silently — business functionality is unaffected
}Send an Idempotency-Key header (or an idempotency_key field per event) with every event. A retry carrying a key this service has already stored for the same application is never stored twice. The response is still 202 Accepted; the duplicate is counted rather than inserted, so a retry is always safe.
{ "ok": true, "accepted": 2, "duplicates": 1, "ids": ["..."], "request_id": "req_..." }