Authentication and scopes
API keys
Create a key under Developer and send it as a bearer token:
Authorization: Bearer hr_live_XXXXXXXXXXXXXXXXXXXXXXXX
A key is bound to one project. Everything it reads or writes is scoped to that project, which is why no endpoint takes a project id.
We store only an HMAC-SHA256 digest, so the plaintext is shown exactly once, at creation. A leaked database row cannot be replayed against the API. Revoking is immediate, and a key can be given an expiry.
Scopes
A credential can be narrower than the person who created it. Read and write are separate grants — mentions:read never implies mentions:write — so a reporting agent can be given a key that cannot delete anything.
| Scope group | Grants | Covers |
|---|---|---|
| projects | projects:read · projects:write | Project settings and plan |
| monitors | monitors:read · monitors:write | Tracked keywords and sources |
| mentions | mentions:read · mentions:write | Collected mentions and their triage status |
| alerts | alerts:read · alerts:write | Alert rules |
| usage | usage:read · usage:write | Quota and provider spend |
| webhooks | webhooks:read · webhooks:write | Webhook endpoints and deliveries |
A call without the required grant returns 403 FORBIDDEN naming the missing scope. Every capability page lists the scope it needs.
Session authentication
Requests carrying a valid dashboard session cookie are also accepted, which lets the dashboard call its own API without minting keys. Session callers hold every scope — narrowing is what API keys are for. They may pass ?project_id= to select among their projects; the first is used by default.
MCP
The MCP server at https://herculradar.com/api/mcp accepts the same bearer token and enforces the same scopes per tool. OAuth 2.1 discovery documents are published at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/mcp for clients that prefer an authorisation flow to a pasted key.
Resource hiding
A resource in a project the credential cannot reach answers 404 NOT_FOUND, not 403. A 403 would confirm that the id exists, which leaks the shape of other tenants’ data.
Good practice
- One key per integration, so revoking one does not break the others.
- Grant read-only unless the integration genuinely writes.
- Never ship a key to a browser or paste one into a model prompt.
- Rotate by creating the new key first, then revoking the old one.