# Incumbently auth.md

How an AI agent gets access to Incumbently. Everything needs an Incumbently workspace; the MCP server and API need a paid plan (Pro or Max). Sign up at https://app.incumbently.com/signin.

## MCP server

- Endpoint: `https://app.incumbently.com/mcp` (Streamable HTTP)
- Protected resource metadata: `https://app.incumbently.com/.well-known/oauth-protected-resource/mcp`
- Authorization server: `https://app.incumbently.com` (metadata at `/.well-known/oauth-authorization-server`)
- OAuth 2.1 authorization code flow with PKCE (`S256`). Scope: `read`.
- Register your client dynamically at `https://app.incumbently.com/oauth/register` (RFC 7591), or use an HTTPS Client ID Metadata Document URL as your `client_id`.
- A person signs in to Incumbently and approves the connection once. After that, refresh tokens keep it working.

## REST API

- Base URL: `https://app.incumbently.com/v1`. OpenAPI: `https://app.incumbently.com/openapi.json`.
- Send `Authorization: Bearer <credential>`. The credential is either:
  - an API key a signed-in user creates in the app under Claude and API (keys start with `inc_live_`), or
  - an OAuth access token from the flow above.
- Calls are metered in credits. One credit returns one company record. `GET /v1/me` shows the balance.

## Register an agent with just an email (auth.md service_auth)

For agents that can't open a browser for OAuth. The person must already have an Incumbently account on Pro or Max.

1. Register: `POST https://app.incumbently.com/agent/identity` with JSON `{"type":"service_auth","login_hint":"person@company.com","agent_name":"Your agent"}`. You get back a `claim_token` (keep it in memory only) and a `claim` block: `user_code`, `verification_uri`, `expires_in` (600) and `interval` (5).
2. Hand off: show your person the `verification_uri` and the 6-digit `user_code`. They sign in to Incumbently as that email, check the request and type the code.
3. Poll: `POST https://app.incumbently.com/oauth/token` with `grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=…` every `interval` seconds. You get `authorization_pending` until they approve, then a normal token response: `access_token`, `refresh_token`, `expires_in`, `client_id`.
4. Use the access token as a Bearer token on MCP, the REST API and A2A. Refresh it at the same endpoint with `grant_type=refresh_token`, the `refresh_token` and the `client_id`.

If the code expires before they finish, `POST https://app.incumbently.com/agent/identity/claim` with `{"claim_token":"…","email":"person@company.com"}` for a fresh code. The registration itself lasts an hour. Errors: `slow_down`, `expired_token`, `access_denied` (declined or too many wrong codes), `invalid_grant`. Anonymous agents and ID-JAG assertions aren't accepted yet.

## A2A agent

- Agent card: `https://app.incumbently.com/.well-known/agent-card.json`. Endpoint: `https://app.incumbently.com/a2a`.
- Uses the same bearer credentials as the REST API.

## Revoking access

People can disconnect MCP clients and revoke API keys in the app at any time. Tokens can also be revoked at `https://app.incumbently.com/oauth/token` (RFC 7009).

## Questions

hello@incumbently.com
