Authentication

Argus keeps three kinds of credential apart on purpose. An API key reads your project and manages connections, pricing, and alerts. A source writes telemetry but reads nothing. Anything destructive or sensitive — deletes, keys, sources, billing changes — needs you signed in to the dashboard. If a source secret ever leaks from an app server, the blast radius is "someone could send you fake events", never "someone could read your spend".

API keys — reading

Create one in Settings → API keys and pick its type. The key is shown once, then stored only as a hash.

apiargus_api_…

For the REST API: scripts, dashboards, cron jobs. Reads everything, and can create or update connections, pricing, and alerts.

mcpargus_mcp_…

For the MCP server only. Agents can read every meter, connect providers and create connect links; the REST API refuses these keys.

Send it on every request:

Authorization: Bearer argus_api_...

A key belongs to one project and sees only that project's data. Revoke it any time from the same Settings table — revocation is immediate.

Some actions need a signed-in dashboard session and refuse every key: any delete (connections, alert rules, custom pricing), creating or revoking keys and sources, and starting a checkout or opening the billing portal.

Sources — writing

A source represents one app that sends telemetry — your API server, a worker, a batch job. Create one in Settings → Telemetry sources and you get two values, shown once:

source_idstring

A public identifier. It names where events came from and goes in a request header, unencrypted.

source_secretstring

Signs every batch you send (HMAC-SHA256). Keep it in your app's secret store — Argus stores it encrypted and can't show it again.

To rotate a source, create a new one and revoke the old — events keep flowing under the new name, and revoked sources are refused immediately.

Responses

Every field in requests and responses is snake_case. A success is the resource itself; a list is { object: "list", data, has_more, next_cursor }. A failure has a stable code and, when one field is to blame, its param:

{ "error": { "type": "invalid_request", "code": "invalid_parameter",
             "message": "…", "param": "limit", "request_id": "…" } }

Errors you'll actually see

401 missing_credentials, invalid_api_key

The bearer key is missing or revoked — or an ingest signature didn't verify.

403 key_type_not_allowed, session_required

An MCP key on the REST API, or an API key on an action that needs you signed in to the dashboard.

400 invalid_parameter

Validation, with the offending field in param and a did-you-mean when it was a typo.