Pixel Pete, the CanaryHub canaryCanaryHub

[ HTTP API ]

The ingest API

One endpoint, plain JSON over HTTPS. The SDK is a convenience — anything that can make a POST request can use CanaryHub: Rust, Go, Python, PHP, a shell script, an Arduino.

endpoint
POST https://ingest.canaryhub.ai/api/v1/eventsAuthorization: Bearer ch_live_YOUR_KEYContent-Type: application/json

Request body

Always a batch — send one event as an array of one. Up to 100 events per request, 512 KB body.

requestjson
{  "events": [    { "type": "event", "name": "signup" },    { "type": "event", "name": "payment", "value": 29, "meta": { "plan": "pro" } },    { "type": "error", "name": "webhook failed", "message": "timeout after 3 retries" }  ]}
type"event" | "error"required

event for business events (silent by default, daily rollup); error for problems (digest by default, louder routing).

namestringrequired

1–200 characters. The identity of the event — the dashboard groups and charts by name, so keep names stable (signup, not signup-user-4812).

messagestringoptional

Detail for errors, up to 2,000 characters.

valuenumberoptional

An amount to aggregate — revenue, counts, milliseconds.

metaobjectoptional

Arbitrary JSON context, up to 4 KB serialized per event.

tsstring (ISO 8601)optional

When it happened, with timezone offset (2026-07-02T10:00:00Z). Defaults to arrival time — set it only when reporting something that happened earlier.

Responses

202

Accepted and stored. Body: {"accepted": n}. This is the only success response — treat everything else as a drop.

400

Invalid batch — malformed JSON, empty array, over 100 events, a bad type, or a field over its size cap. Body: {"error": "..."} with the first problem.

401

Missing, unknown, or revoked API key.

413

Body over 512 KB.

429

Rate limit exceeded. Each key has a budget of 60 events/minute with a burst allowance of 120 — far above normal traffic. If you hit it, batch harder or spread bursts out; events in a 429'd request are not stored.

Examples

pythonpython
import requests, osrequests.post(    "https://ingest.canaryhub.ai/api/v1/events",    headers={"Authorization": f"Bearer {os.environ['CANARY_API_KEY']}"},    json={"events": [{"type": "event", "name": "report-generated"}]},    timeout=5,)
cron job heartbeat-stylebash
# End of a nightly backup script — one line, any language with curl:$ curl -sf -X POST https://ingest.canaryhub.ai/api/v1/events \    -H "Authorization: Bearer $CANARY_API_KEY" \    -H "Content-Type: application/json" \    -d '{"events":[{"type":"event","name":"backup-completed"}]}' || true

The trailing || true keeps the pattern honest: telemetry should never fail your job.

Good citizenship

  • Batch. One request with 20 events beats 20 requests. The rate limit is charged per event, not per request.
  • Fire and forget. Use a short timeout, ignore failures, never retry in a loop from your hot path.
  • Keep keys server-side. ch_live_ keys write to your account — don't ship them in browser bundles or mobile apps. Revoke leaked keys in the dashboard; revocation is immediate.