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 groupGrantsCovers
projectsprojects:read · projects:writeProject settings and plan
monitorsmonitors:read · monitors:writeTracked keywords and sources
mentionsmentions:read · mentions:writeCollected mentions and their triage status
alertsalerts:read · alerts:writeAlert rules
usageusage:read · usage:writeQuota and provider spend
webhookswebhooks:read · webhooks:writeWebhook 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.