OAuth Apps
Build third-party apps that act on behalf of FeatureOS organizations and users via OAuth 2.0.
Introduction
OAuth Apps let you build a third-party application that other FeatureOS organizations can install and that then calls the FeatureOS v3 API on their behalf — without anyone sharing an API key. It follows the OAuth 2.0 authorization code grant.
If you're building an integration that other workspaces will connect (a Slack bot, a Jira sync, an internal tool for your own org), this is what you want. If you just need to script against your own organization, a plain API key is simpler.
Key concepts
| Term | Meaning |
|---|---|
| Owner organization | The org that creates and owns the app (you, the developer). Manages credentials, scopes, and the webhook URL. |
| Target organization | An org that installs your app. Your app acts within this org when using a token issued for it. |
| Actor mode | How a token acts: app (a bot identity owned by your app) or self (on behalf of the consenting user, with that user's role limits). An app may allow one or both. |
| Scope | A permission like posts:read or posts:write that gates what the token can do. See Scopes. |
| Access token | An opaque bearer token (foot_…) used to call the API. Expires in 24 hours. |
| Refresh token | An opaque token (foor_…) used to get a new access token when it expires. See Access Tokens. |
How authentication differs
A normal v3 request needs an API-KEY header (which selects the organization). An OAuth-authenticated request does not:
Authorization: Bearer foot_xxxxxxxxxxxxxxxx
The organization, the acting user, and the allowed scopes are all resolved from the token itself — so you send no API-KEY and no per-user JWT. See Using Access Tokens.
Token formats
| Token | Prefix | Notes |
|---|---|---|
| Client ID | foapp_ |
Public identifier for your app. |
| Client secret | fosec_ |
Shown once at creation (and on rotate). Store securely. |
| Authorization code | fooc_ |
Single-use, expires in 5 minutes. |
| Access token | foot_ |
Bearer token, expires in 24 hours. |
| Refresh token | foor_ |
Rotates the access token. |
Secrets, codes, and tokens are stored hashed and are returned in plaintext exactly once — capture them at creation.
Lifetimes
- Authorization code — single-use, 5-minute TTL.
- Access token — 24 hours. After it expires, use the refresh token.
- Refresh token — rotates the access token in place; valid until the install is revoked.
- An app holds one live token per target organization at a time.
Before you build — checklist
- Decide your actor mode(s): does your app act as a bot (
app), as the connecting user (self), or either? - List the scopes you need — request the minimum. Unused scopes will be declined by cautious admins.
- Set one or more exact
redirect_uris(https only;httpis allowed for loopback hosts —localhost,127.0.0.1,[::1]— for local development). - If you want event notifications, plan your webhook URL and the events you'll subscribe to (requires the
webhooks:managescope). See Webhooks. - Handle token expiry (24h) by refreshing — don't assume a token lives forever.
- Be ready for revocation: an org admin can disconnect your app at any time; expect
401and re-prompt for authorization.
Next steps
- Authorization Flow — register, authorize, consent, exchange.
- Scopes & Actor Modes
- Using Access Tokens
- Webhooks