Documentation / Concepts / Authentication

Authentication

Three ways to connect, all tied to your account: OAuth sign-in for assistants (claude.ai, ChatGPT…), an API key for code and the REST API, or a secret connector URL as a last resort.

Which method should I use?

MethodForGives access toRevocation
OAuth sign-inclaude.ai (web, mobile, Cowork), ChatGPT, Claude Code, any compatible remote MCP clientMCP server only (/mcp)Dashboard → Connected apps, takes effect on the next call
API key normi_…REST API, scripts, CI, the STDIO package @normi/mcp-dvf, CursorREST API and MCP serverCreating a new key revokes the old one
Connector URLClients with neither OAuth nor custom headersMCP server onlyDashboard → Tokens, revocable at any time
Credits always come from your active key
Whichever method you use, every call is charged to your account's active API key. An OAuth connection has no balance of its own: it follows your key, including after a rotation.

OAuth sign-in (MCP server)

Paste https://mcp.normi.fr/mcp into your client, sign in to Normi, then approve the app. No key to copy. See the Claude and ChatGPT guides.

  • First approval: if your account doesn't have an API key yet, a free key (500 credits) is created at that point, after a bot check. An account that already has a key keeps its balance and its plan.
  • Rotation: creating a new key in the dashboard doesn't disconnect your apps; they use the new key from the next call.
  • Key revoked with no replacement: calls fail with 403 no_active_key. Normi never creates a key behind your back; create one and the app resumes.
  • Lifetime: the access token expires after one hour and the client renews it by itself. Signing out of normi.fr doesn't disconnect your apps.
  • Scope: an OAuth token only works on the MCP server. The REST API /v1 requires an API key.

Claude Code

claude mcp add --transport http normi https://mcp.normi.fr/mcp
# then, inside Claude Code:
/mcp

For MCP client developers

A call without credentials returns 401 with a WWW-Authenticate header that points to the protected-resource metadata (RFC 9728). That names the authorization server, which supports dynamic client registration (RFC 7591), the authorization code flow with PKCE (S256) and refresh tokens.

$ curl -i -X POST https://mcp.normi.fr/mcp
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://mcp.normi.fr/.well-known/oauth-protected-resource/mcp"

API key: accepted headers

HeaderRecommended forExample
X-API-KeyREST API (preferred)X-API-Key: normi_abc123
AuthorizationMCP clients (standard Bearer)Authorization: Bearer normi_abc123

Both headers are accepted by the REST API and the MCP server. For standard REST integrations, use X-API-Key.

Examples

curl "https://mcp.normi.fr/v1/transactions?code_postal=75011" \
  -H "X-API-Key: normi_your_token"
# Alternatively — Authorization: Bearer (also accepted by the REST API)
curl "https://mcp.normi.fr/v1/transactions?code_postal=75011" \
  -H "Authorization: Bearer normi_your_token"

MCP configuration (Claude Desktop)

{
  "mcpServers": {
    "normi": {
      "command": "npx",
      "args": ["-y", "@normi/mcp-dvf"],
      "env": {
        "NORMI_API_KEY": "normi_your_token"
      }
    }
  }
}

Token format

Normi tokens have this format:

normi_<base64url(32 random bytes)>

The normi_ prefix makes a Normi token easy to spot in your logs and tells it apart from other secrets.

The raw token is shown only once
At creation, the token is shown in clear text exactly once. Only its SHA-256 hash is stored on the server. If you lose it, you'll need to create a new token (the old one is revoked and your credits are transferred).

Token rotation

Creating a new token in the dashboard automatically and atomically revokes all your previous tokens. The credit balance is transferred to the new token — you don't get a new batch of 500 free credits.

  • Only one active token per account at any time
  • Apps connected with OAuth follow the new token automatically
  • Revocation is immediate — in-flight requests with the old token fail with HTTP 401
  • All data tied to the token (alerts, portfolio) stays accessible with the new token

Security best practices

  • Never commit your token to a Git repository. Use environment variables.
  • On the server side, keep the token in an environment variable (e.g. NORMI_API_KEY). Never expose it in frontend code.
  • If your token is compromised, create a new one immediately from the dashboard. The old one is revoked instantly.
  • Server-side verification uses a constant-time comparison (resistant to timing attacks).