Authentication

Raven accepts three kinds of credentials. All are sent as Authorization: Bearer <token>. For an API key, X-Subscription-Token: <key> also works.

Credential Looks like Get it from Use it for
API key rvn_live_… The dashboard, the CLI, or the device flow Scripts, the REST API, MCP clients without OAuth
OAuth access token rvn_at_… (expires in 1 hour) An MCP client's OAuth sign-in MCP clients such as Claude Code, Codex and Gemini CLI
Browser session a cookie Signing in at ravenoutreach.com The dashboard

API keys

An account can have up to 10 keys. Only a hash of each key is stored, so a key is shown once, when it's created. Keys have the read and write scopes. Revoke a key in the dashboard. A tool holding a key can also revoke it itself, with POST /oauth/revoke token=<key>.

Never put a key in code or a commit. Keep it in a gitignored .env as RAVEN_API_KEY, in your OS keychain (the CLI does this), or in your agent's secret store.

Device flow

The device flow (RFC 8628) is how a CLI or coding agent signs a user up or in. The user clicks one link in a browser, and the agent receives an API key. A new account gets the free credit.

curl -s -X POST https://api.ravenoutreach.com/oauth/device/code \
  -d client_id=my-agent -d "client_name=My agent on $(hostname -s)"
{"device_code": "rvn_dc_…", "user_code": "WDJB-MJHT",
 "verification_uri": "https://ravenoutreach.com/activate",
 "verification_uri_complete": "https://ravenoutreach.com/activate?code=WDJB-MJHT",
 "expires_in": 900, "interval": 5}

Show the user verification_uri_complete and the user_code. The approval page shows the same code, so they can check it matches. Then poll the token endpoint every interval seconds:

curl -s -X POST https://api.ravenoutreach.com/oauth/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d device_code=rvn_dc_… -d client_id=my-agent
Response Meaning
{"error": "authorization_pending"} Keep polling.
{"error": "slow_down"} Poll 5 seconds less often.
{"error": "access_denied"} The user declined. Stop.
{"error": "expired_token"} 15 minutes passed. Start again.
{"access_token": "rvn_live_…", "token_type": "Bearer", …} Done. The key is handed out once.

OAuth for MCP clients

MCP clients that support MCP authorization need only Raven's MCP URL. The flow:

  1. The client calls https://api.ravenoutreach.com/mcp without a token and gets a 401. Its WWW-Authenticate header points to the resource metadata.
  2. The client registers itself and sends the user to a consent page.
  3. The user approves with one click. If they're new, they sign up first.
Protected resource metadata https://api.ravenoutreach.com/.well-known/oauth-protected-resource/mcp
Authorization server metadata https://api.ravenoutreach.com/.well-known/oauth-authorization-server
Registration Dynamic client registration (RFC 7591) at /oauth/register; public clients only (no secret)
Grant Authorization code with PKCE (S256 only); responses include iss (RFC 9207)
Redirect URIs https anywhere, http only for loopback addresses (any port), or a desktop app's own scheme
Scopes read (account, teams, leads), write (create and steer teams, which spends credit)
Resource indicators https://api.ravenoutreach.com/mcp (the default) or https://api.ravenoutreach.com (the REST API); a token works only at the resource it was issued for
Tokens Access tokens last 1 hour. Refresh tokens last 30 days and rotate on every use. Replaying a used refresh token revokes the whole chain.
Revocation POST /oauth/revoke (RFC 7009); users can also disconnect apps in the dashboard

This page as Markdown: /docs/authentication.md