| Credential | Use |
|---|---|
| Stats API key | Read statistics and allowed site metadata |
| Sites API key | Also create/update sites, goals, and custom property configuration where the member's role permits |
| Better Auth session | Dashboard, team membership, personal settings, Google authorization |
| MCP OAuth | AI client's read-only access to explicitly selected sites |
Send API keys in Authorization: Bearer …. A dashboard session cookie cannot replace a key. Keys are scoped to one team, with either all sites or an explicit site list. A full-team key includes future sites; a site-restricted key does not. Expiry, revocation, and membership changes are checked on every call.
Creating a site requires a full-team Sites key. Deleting goals and property configuration requires the owner's Sites key. The API does not provide account passwords, OAuth client secrets, platform administrator access, or arbitrary SQL.
Rate limits
Stats and Sites calls share 600 requests per hour per key. Inspect X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds). On 429, wait for Retry-After seconds. Use bounded exponential backoff for 502/503; do not repeatedly retry bad credentials.
| Status | Meaning and action |
|---|---|
| 400 | Invalid JSON or query combination; correct the request |
| 401 | Missing, expired, revoked, or no longer authorized key |
| 403 | Key type or current role does not allow this operation |
| 404 | Resource absent or outside the key's scope |
| 409 | Resource conflict or configured limit |
| 422 | Unsupported configuration |
| 429 | Rate limit; honor Retry-After |
| 502 / 503 | Analysis service unavailable; retry with backoff |
Errors use JSON such as {"error":"…"}. Keep response logging free of credentials.