Reference
API and schema
v1 contracts for heartbeats, events, suite runs, and authenticated fleet reads.
Reviewed 2026-07-23
The API separates ingest from reads. Ingest endpoints use HMAC; read endpoints accept an administrator session or a valid Bearer token.
Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST |
/api/ingest |
HMAC | Agent heartbeat. |
POST |
/api/ingest/events |
HMAC | Batch of explicit events. |
POST |
/api/ingest/runs |
HMAC | Results and artifacts. |
GET |
/api/fleet |
admin | Aggregated fleet view. |
POST |
/api/auth/login |
token in body | Creates an HttpOnly cookie. |
POST |
/api/auth/logout |
none | Clears the cookie if present. |
GET |
/api/health |
none | Minimal process liveness. |
GET |
/api/ready |
cron Bearer | Redacted runtime and database readiness. |
GET |
/api/cron/costs |
cron Bearer | Provider inventory reconciliation and estimated cost snapshots. |
GET |
/api/cron/retention |
cron Bearer | Expired heartbeat and nonce pruning. |
Writes are disabled while Chalupa runs in demo mode.
Ingest authentication
Required headers:
content-type: application/json
x-chalupa-timestamp: <epoch-seconds>
x-chalupa-nonce: <unique-value>
x-chalupa-signature: v1=<hmac-sha256-hex>
Canonical string:
v1
<METHOD>
<PATH>
<TIMESTAMP>
<NONCE>
<SHA256_HEX_OF_BODY>
The signature uses CHALUPA_INGEST_KEY, which must contain 32 to 1024 bytes
with no leading or trailing whitespace or line breaks. The timestamp allows a
limited window, and each nonce is claimed exactly once.
Heartbeat
{
"version": "1",
"environmentSlug": "demo-harbor",
"environmentName": "Demo Harbor",
"observedAt": "2026-07-23T18:20:00.000Z",
"deployment": {
"provider": "digitalocean",
"providerId": "10001",
"region": "nyc3",
"sizeSlug": "s-2vcpu-4gb",
"launchedAt": "2026-07-23T17:50:00.000Z"
},
"ip": "192.0.2.44",
"uptimeSeconds": 1800,
"containers": [
{
"name": "api",
"state": "running",
"memoryMiB": 312,
"cpuPercent": 4.8
}
],
"reaper": {
"idleChecks": 2,
"checkIntervalSeconds": 300,
"limitMinutes": 45
},
"disk": {
"mountedGiB": 20,
"usedGiB": 1.4
},
"agentVersion": "1"
}
Accepted response:
{
"accepted": true
}
The server can include additional counters or identifiers.
Events
{
"version": "1",
"environmentSlug": "demo-harbor",
"deploymentProviderId": "10001",
"deployment": {
"provider": "digitalocean",
"sizeSlug": "s-2vcpu-4gb",
"region": "sfo3",
"dropletHourlyUsd": 0.04167,
"volumeGiB": 10
},
"events": [
{
"sourceEventId": "evt_demo_launched_001",
"occurredAt": "2026-07-23T17:50:00.000Z",
"kind": "launched",
"reason": "manual"
}
]
}
deployment is required when the payload includes launched and is rejected
when the payload has no launch event. It captures the bounded provider
metadata and launch-time rate needed to account for a short-lived deployment
before the next inventory poll; it never carries a provider credential.
Supported kinds:
launched;sunk;reaper-warning;reaper-destroyed;seed-restored;heartbeat-recovered.
Supported reasons are manual, idle, provider, health, seed, and
unknown.
Suite runs
{
"version": "1",
"environmentSlug": "demo-harbor",
"suiteName": "checkout-e2e",
"runs": [
{
"sourceRunId": "run_demo_20260723_001",
"specName": "create-order",
"status": "passed",
"durationMs": 18420,
"metricName": "workflow-latency",
"metricMs": 1220,
"variant": "baseline",
"artifacts": [
{
"kind": "report",
"store": "fcheap-local",
"stashId": "stash_demo_report_001"
}
]
}
]
}
A request accepts up to 250 runs; each run accepts up to 20 artifacts. The server validates limits, enum values, and duplicates before persisting data.
Fleet
GET /api/fleet returns:
{
"mode": "demo",
"generatedAt": "2026-07-23T18:21:00.000Z",
"totals": {
"environments": 1,
"afloat": 1,
"stale": 0,
"sunk": 0,
"unknown": 0,
"estimatedHourlyUsd": 0.04,
"estimatedMonthToDateUsd": 0.62
},
"environments": []
}
IP addresses, names, and stack details belong only to the authenticated response. Public metadata does not include them.
Operational probes
GET /api/health is an unauthenticated liveness probe. It returns only:
{ "status": "ok" }
GET /api/ready validates the runtime contract and, in database mode, runs a
bounded database probe. It requires Authorization: Bearer <CRON_SECRET> and
returns { "status": "ready" }, or a redacted 503 response. Neither endpoint
returns configuration, provider inventory, or fleet data.
Login
URL-encoded form:
token=<admin-token>
next=/app
next is optional and accepts only relative paths that begin with /, never
//. Successful authentication creates the chalupa_admin HttpOnly cookie.
Do not send the token in a query string.
Errors
The API uses semantic HTTP status codes:
| Code | Case |
|---|---|
202 |
Ingest accepted. |
400 |
Malformed JSON. |
401 |
Invalid session or signature. |
409 |
HMAC nonce already claimed, or deployment assigned to another environment. |
413 |
Body exceeds the endpoint limit. |
422 |
Invalid content type, UTF-8, or schema. |
503 |
Writes deliberately disabled in demo mode. |
Messages must never reveal keys, expected signatures, or sensitive content.