---
title: "Ingest telemetry batch from on-prem instance"
method: POST
path: "/api/v1/telemetry/batch"
tags: ["On-Prem Telemetry"]
---

# Ingest telemetry batch from on-prem instance

`POST /api/v1/telemetry/batch`

Receive and store a batch of telemetry events from an on-prem Compresr instance.
    
    **Required Headers:**
    - `X-API-Key`: Compresr API key (authentication)
    - `X-Compresr-Signature`: HMAC signature (integrity)
    
    **Optional Headers:**
    - `X-Instance-ID`: On-prem instance identifier
    
    **First Request (auto-registration):**
    Include `signing_secret` (`opm_xxx`) in the body - it will be registered
    automatically. `cmp_` API keys are rejected; mint an `opm_` credential
    in the dashboard under Settings -> On-Prem first.

    **Signature Format:**
    ```
    t=timestamp,v1=HMAC-SHA256(timestamp + "." + JSON(payload), signing_secret)
    ```
    
    **Event Types:**
    - `compression`: Counted for billing
    - `error`: Logged only
    - `startup`/`shutdown`: Operational
    
    **Idempotency:**
    Same batch_id within 24h returns success without reprocessing. A batch
    with failed events stays replayable: retry it and already-billed events
    are returned as status "duplicate" (never billed twice).

## Headers

- `x-instance-id` string, nullable — On-prem instance ID
- `x-compresr-signature` string, nullable — HMAC signature
- `X-API-Key` string, required

## Request body

- TelemetryBatchRequest
  - `batch_id` string, required — Unique batch ID (UUID)
  - `instance_id` string, required — On-prem instance ID (UUID)
  - `events` TelemetryEvent[], required — List of telemetry events (max 100 per batch)
    - `event_id` string, required — Unique event ID (UUID)
    - `timestamp` string, required — Event timestamp (ISO8601)
    - `event_type` string, required — Event type (compression, error, startup, shutdown)
    - `model_name` string, required — Compression model used
    - `original_tokens` integer — Original token count
    - `compressed_tokens` integer — Compressed token count
    - `tokens_saved` integer — Tokens saved (original - compressed)
    - `duration_ms` integer — Processing duration in milliseconds (max 1h)
    - `metadata` object — Additional metadata (max 10KB, 50 keys, 3 levels deep)
    - `event_hmac` string, nullable — Per-event HMAC-SHA256(api_key, canonical_event_bytes) computed by on-prem at insert time. Optional — older on-prem builds don't send it. The platform rejects events whose tag doesn't verify.
  - `identity` IdentityManifest — On-prem identity manifest, sent in each upload for rebirth detection. The on-prem instance persists this manifest in ``/data/identity.json`` HMAC-bound to the api_key on first authenticated request. Subsequent uploads carry the same values. If we see a *new* ``instance_id`` or an earlier ``created_at`` for the same api_key, it signals that the operator deleted the local manifest — typically an attempt to reset a per-instance grace period or quota.
    - `instance_id` string, required — UUID matching /data/identity.json
    - `api_key_hash` string, required — SHA-256 hex of the api_key the on-prem instance was first bound to
    - `created_at` string, required — ISO-8601 timestamp manifest was created
  - `signing_secret` string, nullable — Signing secret for HMAC verification (include on first request only)

## Response `200`

Successful Response

- TelemetryBatchResponse
  - `success` boolean, required — Whether batch was accepted
  - `batch_id` string, required — Echo of batch ID
  - `events_received` integer, required — Number of events received
  - `events_stored` integer, required — Number of events stored
  - `message` string, nullable — Additional message
  - `events_billed` integer — Compression events charged through the billing pipeline
  - `events_unbilled` integer — Compression events recorded but not charged
  - `events_duplicate` integer — Compression events skipped because an earlier delivery of this batch already billed them (replay protection)
  - `events_failed` integer — Compression events that were not recorded; the batch is left replayable so a retry reprocesses exactly these events
  - `event_results` TelemetryEventResult[], nullable — Per-event billing outcomes for compression events
    - `event_id` string, required — Echo of the on-prem event ID
    - `status` 'billed' | 'recorded_unbilled' | 'failed' | 'duplicate', required — Billing outcome: billed | recorded_unbilled | failed | duplicate
    - `reason` string, nullable — Reason code when status is not 'billed'

## Other responses

- `400` — Invalid request body
- `401` — Invalid API key or signature
- `409` — Duplicate batch (idempotency)
- `422` — Validation Error
- `500` — Internal server error

---

[API](https://skmtc.net/compresr/apis/compresr-platform-api.md) · [All operations](https://skmtc.net/compresr/apis/compresr-platform-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/compresr/compresr-platform-api/versions/93ee959dfa51/schema)
