# Financier authentication for agents

How an agent obtains credentials for the Financier API and MCP server, uses them, and handles errors and revocation.

## Discover

Follow the chain from the API to the authorization server; every document links to the next.

- [Protected resource metadata, REST API (RFC 9728)](https://financier.sh/.well-known/oauth-protected-resource)
- [Protected resource metadata, MCP server](https://financier.sh/.well-known/oauth-protected-resource/mcp)
- [Authorization server metadata (RFC 8414), with agent_auth](https://financier.sh/.well-known/oauth-authorization-server/auth)
- [OpenID configuration](https://financier.sh/auth/.well-known/openid-configuration)
- [Client registration (RFC 7591)](https://financier.sh/auth/oauth2/register)
- [Agent identity (no account needed)](https://financier.sh/agent/identity)

```http
GET https://financier.sh/.well-known/oauth-protected-resource

GET https://financier.sh/.well-known/oauth-authorization-server/auth
```

The protected resource metadata names the issuer (https://financier.sh/auth) in authorization_servers. The issuer's metadata names the authorization, token and registration endpoints, and its agent_auth block names the identity and claim endpoints.

Every 401 from the API or MCP server carries WWW-Authenticate: Bearer resource_metadata="…" pointing at the protected resource metadata.

## Pick a method

| | |
| --- | --- |
| Acting for a person, interactively | OAuth 2.1 authorization code with PKCE. |
| A person's own script or agent | API key created by that person, header x-api-key. |

There is no anonymous access to account data. Every credential belongs to one person's account, and accounts are invite-only for now. Without an account, use the docs MCP server, which needs no credentials.

## Register

Register an OAuth client with RFC 7591 dynamic client registration at https://financier.sh/auth/oauth2/register, or create one under Settings, Developer. Public clients use token_endpoint_auth_method "none" and PKCE.

## Claim

Send the person to https://financier.sh/auth/oauth2/authorize with response_type=code, your client_id, redirect_uri, scope (for example "financier:read financier:write offline_access"), and a PKCE code_challenge. They sign in and approve the scopes on the consent screen.

## Exchange

POST the code and code_verifier to https://financier.sh/auth/oauth2/token (grant_type=authorization_code). Use grant_type=refresh_token with offline_access to renew.

## Use the access_token

```sh
curl https://financier.sh/api/v1/plan/view -H "Authorization: Bearer $ACCESS_TOKEN"
```

The same token works on the MCP server at https://financier.sh/mcp.

## Agents without an account

An agent can start on its own: it gets a sandbox-only identity at once, and a person claims it later. The authorization server metadata carries this as agent_auth (identity_types_supported: anonymous).

1. Get an identity. The response has an identity_assertion and a one-time claim_token.

```http
POST https://financier.sh/agent/identity
Content-Type: application/json

{"type":"anonymous"}
```

2. Exchange the assertion for an access token (one hour; exchange again to renew).

```http
POST https://financier.sh/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>
```

Until claimed, the token reaches the sandbox bank only (provider demo) and cannot register webhooks.

3. To act for a real person, start a claim with their email and show them the user_code.

```http
POST https://financier.sh/agent/identity/claim
Content-Type: application/json

{"claim_token":"clm_…","email":"person@example.com"}
```

4. The person signs in at https://financier.sh/claim and enters the code within 10 minutes. Poll every 5 seconds; authorization_pending until then.

```http
POST https://financier.sh/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_…
```

The answer carries an access token for the person's account and a new identity_assertion. Every pre-claim token stops working at that moment. The person can revoke the agent under Settings, Developer.

## Errors

| | |
| --- | --- |
| 401 | Missing or invalid credential. Read WWW-Authenticate and start at Discover. |
| 403 | Valid credential, but not allowed: API keys and tokens cannot manage credentials. |
| 429 | Rate limited. Wait Retry-After seconds. |

## Revocation

People revoke API keys and OAuth clients under Settings, Developer; deleting the account revokes everything. A revoked credential returns 401 on its next use.
