---
title: OAuth2 Apps
description: Integrate your third-party app with Futrou using OAuth2.
---

Futrou supports dynamic OAuth2 app registration for automation — a third-party app doesn't need to be registered by hand before it can request access to Futrou. Apps are created on the fly and can't be pre-registered from the dashboard.

An app not connected to any workspace is automatically deleted shortly after registration — it must always register again before its next use.

![OAuth2 authorization screen showing the app's name, icon, and requested workspace access](/img/docs/v2/oauth2-screen.png)

## Auto-discovery

An app finds Futrou's authorization and token endpoints through [OAuth 2.0 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414) (RFC 8414):

```bash
curl https://api.futrou.com/.well-known/oauth-authorization-server
```

```json
{
  "issuer": "https://api.futrou.com",
  "authorization_endpoint": "https://api.futrou.com/v2/auth/oauth2/authorize",
  "token_endpoint": "https://api.futrou.com/v2/auth/oauth2/token",
  "revocation_endpoint": "https://api.futrou.com/v2/auth/oauth2/revoke",
  "registration_endpoint": "https://api.futrou.com/v2/auth/oauth2/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "code_challenge_methods_supported": ["S256"]
}
```

## Registration

The app registers itself the first time it connects, using [OAuth 2.0 Dynamic Client Registration](https://www.rfc-editor.org/rfc/rfc7591) (RFC 7591) against the `registration_endpoint` from discovery — no manual setup in the dashboard:

```bash
curl -X POST https://api.futrou.com/v2/auth/oauth2/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My Integration",
    "logo_uri": "https://myapp.example.com/icon.png",
    "redirect_uris": ["https://myapp.example.com/callback"],
    "token_endpoint_auth_method": "none"
  }'
```

Futrou returns a `client_id` for the app to use in the authorization step below:

```json
{
  "client_id": "app_8f2c1a9b",
  "client_name": "My Integration",
  "logo_uri": "https://myapp.example.com/icon.png",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "client_id_issued_at": 1755190800
}
```

`logo_uri` is optional but recommended — Futrou shows it as the app's icon on the authorization screen, so people approving the app can recognize it at a glance.

Registration itself grants no access. It only creates a client identity — the app can't do anything with just a `client_id` until a person completes the authorization step and approves it for a workspace.

## Authorization

Once registered, the app runs the standard OAuth2 authorization code flow with PKCE against `https://api.futrou.com/v2/auth/oauth2/authorize` and `https://api.futrou.com/v2/auth/oauth2/token`. You approve it for a specific workspace, issuing a [workspace API token](/docs/apikeys/#workspace-api-tokens) with a role no higher than your own in that workspace.

## Security

Because registration is open and unauthenticated, the fields an app supplies — `client_name`, `logo_uri`, `redirect_uris` — are self-asserted and not verified by Futrou. Treat the registration step as creating an identity claim, not a trust decision: the actual security boundary is the authorization screen, where a person decides whether to grant *that* client access to *their* workspace.

- **PKCE is required.** Every authorization request must include a `code_challenge`, closing the interception risk that comes with not requiring a client secret.
- **`redirect_uris` are matched exactly** at authorization time against what was registered — an app can't redirect the authorization code anywhere it didn't declare up front.
- **Registration is rate-limited** per IP to prevent abuse of the registration endpoint itself.
- **A convincing name or logo isn't proof of identity.** Since both are self-asserted, they can be copied by anyone. Before approving an app, always check the domain in its `redirect_uris` on the authorization screen and confirm you trust it — the same way you'd check a link before clicking it. A trustworthy-looking name or icon is not a substitute for verifying the domain yourself.