API

HTTP API

A plain HTTPS API over the same seven read operations the AI connector exposes. One key, one header, JSON back. Use it from a script, Zapier, Make or your booth software to check which events have audio ready, pull a gallery link, or read gallery stats, without opening the dashboard.

Who can use it

  • Operators on the Monthly plan (Annual counts: it is the same unlimited plan billed yearly). Pay-per-event accounts see the key card locked in Settings, and a key on an account that leaves the plan answers 403 plan_required until it is back.
  • Each key belongs to one operator and reads that operator’s own account only. There are no third-party app credentials; a vendor building for many operators uses the MCP connector and OAuth.
  • Phase 1 is read-only. Creating or changing events and starting a clean stay in the dashboard and the connector for now.

API keys

In the dashboard open Settings, then Account, and find the API keys card. Name the key after what will use it and click Create key. The full key is shown once; copy it then, because only its hash is kept. Up to 5 active keys per account. Revoke a key from the same card and anything using it stops at once.

Format
hha_live_ followed by 43 letters and digits
Stored as
SHA-256 hash only. Lost keys cannot be recovered; revoke and create a new one.
Shown
Once, at creation. The card lists each key by its first characters and last-used date.
Scope
Read, your own account. Scopes are fixed in Phase 1.

Authentication

Send the key as a bearer token on every request. Nothing else is needed: no sign-in, no session, no OAuth.

bash
curl "https://www.happyhearaudio.com/api/v1/events?query=Rivera&from=2026-11-01&to=2026-11-30&limit=10" \
  -H "Authorization: Bearer $HHA_API_KEY"

A missing or unknown key answers 401 with a WWW-Authenticate: Bearer header; a revoked key answers 401 revoked_key. Keep the key server-side. It is as sensitive as your password: anyone holding it can read every event in the account.

Making calls

Base URL https://www.happyhearaudio.com/api/v1. All endpoints are GET and answer JSON. Filters go in the query string and ids in the path. The full list, with parameters and example responses, is on the API reference.

EndpointWhat it answers
GET /eventsSearch your events
GET /events/needing-attentionList events that need a look
GET /events/{id}Get one event
GET /events/{id}/audio-statusCheck audio status on an event
GET /events/{id}/gallery-linkGet the gallery link
GET /events/{id}/gallery-statsGet gallery stats
GET /account/planGet your plan and usage

Errors are always one shape: { "error": { "code", "message" } }. A validation error adds issues naming the field.

400 Bad Request
{
  "error": {
    "code": "invalid_request",
    "message": "A parameter is missing or malformed.",
    "issues": [
      {
        "field": "limit",
        "message": "Too big: expected number to be <=100"
      }
    ]
  }
}

Limits

Requests
60 per 60 seconds, per key
Headers
X-RateLimit-Limit and X-RateLimit-Remaining on every answer; Retry-After (seconds) on a 429
Result size
Up to 100 events per search; up to 500 messages per event
Keys
5 active per account

Back off for Retry-After seconds and retry. Polling an event every few seconds is fine; polling it in a tight loop is what the limit is for.

What is never exposed

The API reads the same allow-listed views as the connector. None of the following is in any response, with any key, on any plan:

  • Guest audio, in any form (no file, no URL, no stream)
  • Transcripts and any words a guest said
  • Caller phone numbers and SMS bodies
  • Speaker names and emotion tags
  • Gallery share codes (only whether one is set)
  • Storage paths, signed URLs and Twilio identifiers
  • Card, invoice or payment details
Guest privacy is the reason this API exists as a read-only surface over states and counts. If your integration needs audio or text, it does not go through here; email hello@happyhearaudio.com and describe it.

Versioning

The version is in the path (/api/v1/). Within v1, fields are only ever added, never renamed or removed, and a new optional parameter never changes the answer to an old request. Anything that would break an existing client ships as /api/v2/ with v1 kept running for at least 90 days and the date announced on the changelog. Read responses by field name, not position, and ignore fields you do not know.

The machine-readable description is /api/v1/openapi.json (OpenAPI 3.1), generated from the same code that validates each request.

bash
curl https://www.happyhearaudio.com/api/v1/openapi.json

A complete example

Set the key once, then ask which events still need a look:

bash
export HHA_API_KEY="hha_live_…"

curl "https://www.happyhearaudio.com/api/v1/events/needing-attention" \
  -H "Authorization: Bearer $HHA_API_KEY"