punchline!

API

Keys and authentication

Every API request carries a key that belongs to one site. The key decides which site you can read and what you're allowed to change.

Create a key

  1. In the dashboard, open Site settings → API and AI access. Only owners and admins of the site can see it (roles).
  2. Under Keys, give the key a name you'll recognize later, like looker or nightly-sync.
  3. Pick what it can do, then create it.
  4. Copy the key straight away. It's shown once; Punchline keeps only a SHA-256 fingerprint of it and the last four characters, so nobody can show it to you again.

Keys look like pk_live_ followed by 32 letters and digits. The Keys table lists each key's name, last four characters, scopes, creation date and when it was last used.

Send it

Put the key in the Authorization header as a Bearer token on every request:

curl https://app.punchlineanalytics.com/v1/sites \
  -H "Authorization: Bearer $PUNCHLINE_API_KEY"

Keys aren't accepted in query strings or request bodies. A missing, malformed or revoked key gets a 401 with the code invalid_api_key.

Scopes

Scope Ticked in the dashboard as Allows
read Every key has it Every GET endpoint, POST /v1/query and POST /v1/exports
events:write Can send events POST /v1/events and POST /v1/handoffs
admin Can manage Alerts, goals, event triggers and URL parameters (/v1/alerts, /v1/goals, /v1/triggers, /v1/url-parameters), and MCP tools that make changes

Each endpoint in the API reference states the scope it needs. Calling one without it returns 403 insufficient_scope. Scopes are fixed when a key is created; to change them, create a new key and revoke the old one.

Give each system the smallest key that works:

  • A BI tool or a dashboard script needs read only.
  • Your backend sending signups or purchases needs Can send events. It can also read, so keep it server-side.
  • Only automation that sets up alerts and goals for you needs Can manage.

One key, one site

A key works on exactly the site it was created for. Endpoints that take a site_id check it matches; a different site returns 404 site_not_found, the same as a site that doesn't exist, so a key can't be used to probe for other sites. On GET endpoints you can leave site_id out and the key's site is used. GET /v1/sites tells you which site a key belongs to.

For several sites, create a key on each.

Revoking and rotating

Revoke a key in the Keys table. It stops working on the next request, everywhere.

To rotate without downtime:

  1. Create a new key with the same scopes.
  2. Deploy it where the old key is used.
  3. Check the old key's Last used time stops moving (it updates at most once a minute).
  4. Revoke the old key.

Rotate when someone who had a key leaves, when a key may have been exposed, and on whatever schedule your security policy sets.

Keeping keys safe

  • Use keys from servers, scripts and tools you control. Never put one in a web page, a mobile app or anything else a visitor can download: anyone who can read it can read your analytics.
  • Keep keys in a secret manager or environment variables, not in source control.
  • If a key leaks, revoke it first, then work out where it went. The Last used time shows whether it has been used.

Signing in instead of a key (MCP)

AI assistants that support MCP sign-in (OAuth 2.1 with PKCE), such as Claude, connect without a key: you sign in to Punchline, pick a site, and approve. The connection reads by default; it can only make changes if you tick Also let it make changes on the approval screen. Connected apps are listed under Site settings → API and AI access, with when each was last used, and you can disconnect any of them there. Sign-in tokens work only on the MCP server, not on the REST API. See Connect your AI assistant.

Keys and team roles

Keys belong to the site, not to the person who made them, so they keep working when that person leaves the team. Removing someone from the site doesn't revoke keys they created: review the Keys table when people leave. Saved reports made through a key belong to the site's owner.

Ask the docs

Answers come from these docs only, written by Claude (Anthropic). Your question is sent to answer it, and isn't stored.