Skip to content
Back to home

§ DOCUMENTATION

API Reference

REST API endpoints for the Execlave control plane.

§ 00

Base URL & Authentication

Base URL: https://api.execlave.com# All endpoints below are versioned under /api/v1 # Two authentication methods: # 1. API Key (recommended for SDK/automation)curl -H "X-API-Key: exe_prod_your_key_here" ... # 2. Logto JWT (used by the dashboard)curl -H "Authorization: Bearer <logto_jwt>" ...

All endpoints require authentication. API Keys are prefixed with exe_prod_ (production), exe_stg_ (staging), or exe_dev_ (development). Generate keys from Settings → API Keys.

§ 01

Response format

Success (single item)

{ "data": { "id": "uuid", ... } }

Success (list)

{ "data": [...], "meta": { "total": 42 } }

Error

{ "error": { "code": "VALIDATION_ERROR", "message": "...", "fields": { ... } } }
§ 02

Agents

§ 03

Traces

§ 04

Policies

§ 05

Access Grants

§ 06

Webhooks

§ 06.1

Verifying webhook signatures

Every outbound delivery is signed with HMAC-SHA256 using your webhook's signing secret. The current scheme (v2) binds a timestamp into the signed string to prevent replay attacks; the legacy v1 scheme remains supported for in-flight deliveries during a deploy.

HeaderDescription
X-Execlave-Signaturesha256=<hex> — HMAC of the signed payload.
X-Execlave-Signature-Versionv1 or v2. Default when the header is absent: v1.
X-Execlave-TimestampUnix-seconds timestamp from when the delivery was signed. Sent on v2 only. Receivers should reject deliveries outside a ±5-minute window.
X-Execlave-Idempotency-KeyStable per logical event (deterministic in org/event/body) — same value across retries. Use this to dedupe on the receiver.

Receiver-side verification (Node.js):

const crypto = require('crypto'); function verify(headers, rawBody, secret) {  const ts = headers['x-execlave-timestamp'];  const sig = headers['x-execlave-signature'].replace('sha256=', '');  const ver = headers['x-execlave-signature-version'] ?? 'v1';   const signedPayload = ver === 'v2' ? `${ts}.${rawBody}` : rawBody;  const expected = crypto.createHmac('sha256', secret)    .update(signedPayload)    .digest('hex');   // Constant-time comparison  const a = Buffer.from(expected, 'hex');  const b = Buffer.from(sig, 'hex');  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {    throw new Error('Invalid webhook signature');  }   // v2: enforce a sliding replay window (±5 minutes recommended)  if (ver === 'v2') {    const now = Math.floor(Date.now() / 1000);    if (Math.abs(now - parseInt(ts, 10)) > 300) {      throw new Error('Webhook timestamp outside replay window');    }  }} // Idempotency: dedupe on X-Execlave-Idempotency-Key (stable across retries).// Persist the key with a short TTL (e.g. 24h) and reject duplicates.

Important: verify against the raw request bytes, not a re-serialized JSON object — any whitespace or key-order change will break the HMAC comparison.

§ 07

Rate limits

Route groupLimitWindow
Control plane (agents, policies, etc.)100 requestsper minute
Trace ingestion (POST /traces/ingest)1,000 requestsper minute
Policy enforcement (POST /policies/enforce)10,000 requestsper minute

Limits are per organization. The enforcement bucket is sized for SDK hot-path traffic and can be tuned per deployment via ENFORCEMENT_RATE_LIMIT_PER_MINUTE. When rate limited, the API returns 429 Too Many Requests with a Retry-After header. The frontend API client and SDKs handle retries automatically with exponential backoff.