Agent telemetry API
The endpoints guard-agent uses to ship security events and metrics to the Core API: ingestion, encryption, status, and rule fetch.
The agent telemetry surface is the inbound side of the Core API: it receives security events, metrics, and health signals from every guard-agent install and issues the dynamic rules those agents enforce. All endpoints on this surface authenticate via X-API-Key header. No session or JWT is required or accepted.
Endpoints
The six endpoints below form the complete agent-facing surface. Each requires the X-API-Key header carrying a valid project API key. The optional X-Project-Id header can disambiguate when a single key covers multiple projects; omit it when the key is already project-specific.
POST /events
Ingests a batch of security events captured by the guard middleware. The request body is a BatchTelemetryRequest containing an events array (up to 10,000 SecurityEvent items), an optional metrics array, and optional metadata fields (batch_id, agent_version, guard_version). The response is a TelemetryResponse reporting how many events and metrics were received, processed, and dropped (e.g. events outside the allowed timestamp window).
Before processing the payload the server applies three rate-limit checks in sequence: a per-IP token bucket, a per-API-key token bucket, and a per-project token bucket. Any of these can return 429. The server also enforces a maximum payload byte size; oversized requests are rejected with 413 Content Too Large before deserialization.
POST /events/encrypted
Identical semantics to POST /events but the payload is AES-256-GCM encrypted. The request body is an EncryptedTelemetryRequest with a single encrypted_payload field (Base64-encoded ciphertext) plus the same optional metadata fields. The server decrypts the payload using the project's stored encryption key before processing it through the same pipeline as a plain batch.
Encryption key management is covered in Encryption key rotation.
POST /metrics
Dual-purpose heartbeat and metrics endpoint. When the request body (BatchTelemetryRequest) contains non-empty events or metrics arrays the server processes them and returns a TelemetryResponse. When the body is empty or omitted the server records an agent heartbeat and returns a HeartbeatResponse with an acknowledged flag, a server timestamp, and a next_heartbeat_interval hint in seconds.
Agents use this endpoint to signal liveness between full event batches. The server tracks the last-seen timestamp for each project to populate the agent status dashboard.
POST /status
The endpoint the agent uses to push its own health and status. The request body is an AgentStatusRequest carrying agent_id (optional - the agent omits it, and the server derives agent-<project id> from the project when absent), timestamp, status (healthy, degraded, or failed), uptime (seconds), events_sent, events_failed, buffer_size, last_flush (optional), and errors (a list of recent error messages). The response is an AgentStatusPostResponse with a success flag and a message describing how the status was processed.
The agent posts this from send_status to report its buffering and delivery health; it does not read status back.
GET /status
Returns the current connection and configuration status for the authenticated project. The response is an AgentStatusResponse with status (a connection-state string), project_id, project_name, a server timestamp, and a features map of { feature_name: bool } entries indicating which optional capabilities (e.g. encryption, dynamic rules) are active on the project.
This endpoint is for reading current status; tooling and dashboards call it to confirm connectivity and discover which features are enabled. The status value is the same connection state the dashboard's Agents tab shows (never-connected, healthy, degraded, failed, or stale after 10 minutes of silence), resolved from the latest heartbeat, status post, event, or metric.
GET /rules
Fetches the active dynamic rules for the authenticated project. The response is a DynamicRulesResponse containing the current rule set and a version integer. Agents compare the received version against their cached version and only reapply rules when the version advances.
Authentication for this endpoint uses the same X-API-Key / X-Project-Id pair as the ingestion endpoints, validated directly by verify_api_key in guard_core_api/services/api_keys_service.py. A missing or invalid key returns 401 Unauthorized with the detail "Invalid API key or project ID".
Error responses
All agent-facing endpoints share a common set of error conditions:
| Status | Condition |
|---|---|
| 401 | Invalid X-API-Key - raised by authenticate_telemetry_project when the key (or key/project pair) does not resolve to a project |
| 403 | Source IP not in the project's allowed CIDR list (when an IP allowlist is configured) |
| 429 | Token bucket exhausted - per-IP, per-API-key, or per-project limit exceeded; response includes Retry-After in seconds |
| 422 | Missing required X-API-Key header, or request body fails Pydantic schema validation |
| 413 | Payload exceeds the maximum byte size - rejected before deserialization |
| 400 | Encrypted endpoint called on a project without an encryption key, or payload decryption failed |
When agents receive a 429 they must buffer and retry rather than drop events. The back-off and retry strategy is documented in Agent buffering.