Skip to content

Telemetry ingest API

The telemetry ingest API accepts telemetry_event records. Most customers do not call this directly — Claresia’s Telemetry Pipeline pulls from the LLM platform’s audit log automatically.

You do call this directly if:

  • You are running Mode C BYOC and the customer-side redaction Lambda / Function App emits envelopes
  • You have a custom LLM platform not yet covered by a built-in pull connector
  • You are emitting synthetic test telemetry for load testing
POST /api/v1/telemetry/events
Authorization: Bearer <jwt>
X-Claresia-Tenant: dainese
Content-Type: application/json
POST /api/v1/telemetry/events
{
"skill_id": "gatespic.incident-postmortem",
"skill_version": "1.4.2",
"archetype_id": "firmware_engineer",
"user_id": "user:marco.mazzolin@dainese.it",
"llm_platform": "anthropic-claude-enterprise",
"llm_model": "claude-sonnet-4.7",
"ts": "2026-05-03T14:22:18.500000Z",
"success": true,
"latency_ms": 2317,
"tokens_in": 4823,
"tokens_out": 1421,
"cost_usd_estimate": 0.041,
"error_code": null
}

Response:

HTTP/1.1 201 Created
{
"record_id": "01933a95-...",
"provenance_hash": "h7Vw3K...",
"provenance_cosign": "Mq4z8L..."
}
POST /api/v1/telemetry/events:batch
{
"events": [
{ "skill_id": "...", ... },
{ "skill_id": "...", ... },
{ "skill_id": "...", ... }
]
}

Response:

HTTP/1.1 201 Created
{
"accepted": 3,
"failed": 0,
"records": [
{ "record_id": "01933a95-...", "provenance_hash": "...", "provenance_cosign": "..." },
{ "record_id": "01933a96-...", "provenance_hash": "...", "provenance_cosign": "..." },
{ "record_id": "01933a97-...", "provenance_hash": "...", "provenance_cosign": "..." }
]
}

Max 1000 events per batch. Larger batches return 400 Bad Request.

FieldTypeRequiredNotes
skill_idstringyesMust reference a Skill IR registered in the tenant
skill_versionstring (semver)yes
archetype_idstringyesMust exist in the cc-051 archetype bundle
user_idstringyesFormat user:<email> or user:<scim_external_id>
llm_platformenumyesanthropic-claude-enterprise, microsoft-copilot-m365, openai-chatgpt-enterprise, google-gemini-workspace, slack, custom:<name>
llm_modelstringrecommendede.g., claude-sonnet-4.7, gpt-5, gemini-2.5-pro
tsRFC3339yesMicrosecond precision recommended
successbooleanyes
latency_msintegeryes
tokens_inintegeryes
tokens_outintegeryes
cost_usd_estimatefloatyesUse 6-decimal precision
error_codestring | nullyes if success=false

The endpoint accepts the event, computes provenance, writes to the per-tenant ClickHouse cluster, and triggers downstream Command Center surface refresh.

The customer-side redaction Lambda calls this endpoint with the envelope only — no payload, no PII. Claresia accepts and stores the envelope; no content-bearing fields are accepted in Mode C (they’re rejected with 400).

Send Idempotency-Key: <unique-key> header:

POST /api/v1/telemetry/events
Idempotency-Key: dainese:2026-05-03T14:22:18.5Z:user:marco:gatespic-incident

Repeat calls with the same key return the existing record (idempotent retry). Keys are scoped per tenant + 24h TTL.

  • tokens_in + tokens_out must equal the LLM platform’s reported total (within ±2% tolerance to allow for platform-specific rounding)
  • cost_usd_estimate is estimated by the customer; Claresia computes its own estimate from (tokens_in × price_in + tokens_out × price_out) and stores both for reconciliation
  • latency_ms must be > 0 and < 600000 (10 minutes)

Sample customer-side connector (Python, Mode C)

Section titled “Sample customer-side connector (Python, Mode C)”
import asyncio
import httpx
from datetime import datetime, timezone
async def emit_envelope(claresia_endpoint: str, jwt: str, tenant: str, event: dict):
async with httpx.AsyncClient() as client:
# Strip payload-bearing fields (keep envelope only)
envelope = {
k: v for k, v in event.items()
if k in {"skill_id", "skill_version", "archetype_id", "user_id",
"llm_platform", "llm_model", "ts", "success", "latency_ms",
"tokens_in", "tokens_out", "cost_usd_estimate", "error_code"}
}
idempotency_key = f"{tenant}:{envelope['ts']}:{envelope['user_id']}:{envelope['skill_id']}"
r = await client.post(
f"{claresia_endpoint}/api/v1/telemetry/events",
json=envelope,
headers={
"Authorization": f"Bearer {jwt}",
"X-Claresia-Tenant": tenant,
"Idempotency-Key": idempotency_key,
},
)
r.raise_for_status()
return r.json()

See Hub API — telemetry events are queryable as record_type=telemetry_event records.

HTTPReason
400Schema validation failed (see detail)
401Bearer token invalid or expired
403Service account lacks telemetry:write scope
409Idempotency conflict (different payload, same key)
413Batch too large (>1000 events)
422Skill IR not registered for this tenant
429Rate limit (see Retry-After)
503Downstream Hub temporarily unavailable; retry with exponential backoff