API

Two surfaces, with two different credentials, and one of them is not finished.

Writing: the ingest API

This is the public API. One endpoint, one credential, one shape, documented in full in the ingestion reference.

curl -X POST https://reportshq.org/ingest \
    -H "X-ReportsHQ-Key: rhq_your_project_key" \
    -H "Content-Type: application/json" \
    -d '{"events":[{"name":"commerce.order.created","value":4250,"currency":"USD"}]}'

The key is public by design: it ships inside your application, and it grants exactly one capability, appending events to one project. It can never read.

To check a key points where you think it does:

curl -X POST https://reportshq.org/ingest/verify -H "X-ReportsHQ-Key: rhq_your_project_key"

That returns the project's name and nothing else, so a write credential never becomes a way to read the account behind it.

Reading: bearer authenticated, and not yet self-serve

The read endpoints authenticate with a personal access token in an Authorization header:

curl "https://reportshq.org/api/projects/42/events?name=commerce.order.created&limit=50" \
    -H "Authorization: Bearer <token>"

Pagination is keyset rather than offset: pass next_cursor back as before. See the ingestion reference for the response shape and the reasoning.

The gap worth stating plainly: there is currently no way to mint a standalone API token from the interface. The token that works is the one behind your session cookie, which is issued at sign-in and not intended to be copied into scripts. So the read API is real and works, but it is not yet something you can integrate against properly, and it is not versioned or stable.

Issuing revocable per-project API tokens is the missing piece. Until it exists, treat the read endpoints as internal.

Why there is no generated reference here

buddy generate:openapi produces a specification with several hundred paths, almost all of which are routes the framework mounts by default rather than part of this product. Publishing it would document endpoints that are not ReportsHQ's and, in some cases, are not mounted at all, and a reader cannot tell which is which. A reference that cannot be trusted is worse than none.

When the read API has its own credentials and a stable surface, it gets a reference generated from that surface alone.

Getting data out today