Overview
The Mighty API authenticates requests with OAuth 2.0 or with an API key. With OAuth, a third-party application redirects a user to Mighty, the user signs in and approves a set of scopes, and your application receives a short-lived access token that acts on behalf of that user against the GraphQL API. This is fundamentally different from the Admin REST API, which uses a long-lived Bearer token tied to a Network admin. Pick the one that matches your integration:Why OAuth 2.0
The Mighty API is designed for third-party applications that act on behalf of an end user — a member reading their feed in a custom mobile app, a host pulling their Network into a back-office dashboard, an AI agent summarizing a space the user belongs to. The auth model has to answer two questions a static API key can’t:- Whose data is this? Every Mighty API call resolves against a specific user’s permissions in a specific Network. A member token can only see what that member can already see in the product; a host token additionally exposes host-level fields. There is no “superuser” mode and no way for a third-party app to read data the authorized user can’t.
- Did the user actually consent? Before an application receives a token, the user is shown a consent screen listing the application name and the scopes it’s requesting, and explicitly approves. Mighty — not the application — collects the password. The application never sees the user’s credentials and can never act beyond the scopes the user approved.
- Delegated access without credential sharing. Users authorize applications through Mighty’s login flow. Applications never handle passwords, MFA codes, or session cookies.
- Scoped, revocable tokens. Tokens are bound to a specific user, application, and scope set, with a short expiry. A leaked token has a small blast radius; users (and hosts) can revoke an application’s access without rotating their password.
- A model that fits every client type. Server-side web apps use the Authorization Code flow with a client secret. Mobile, desktop, and single-page apps use Authorization Code + PKCE and ship no secret at all. Both target the same authorization server and the same token endpoint.
- An ecosystem of tooling. OAuth 2.0 client libraries exist for every language and framework — there’s no Mighty-specific SDK to learn, and standard tools (Postman,
curl, framework auth middleware) work out of the box. Mighty publishes the canonical endpoints at/.well-known/oauth-authorization-serverper RFC 8414.
Create an OAuth application
Before your app can request tokens, a host or admin must register an OAuth application in the Network. The application provides the Client ID (and, for confidential clients, Client Secret) you’ll use in the flows below, along with the redirect URIs and allowed scopes. For the full walkthrough — client types, redirect URI rules, scope catalog, secret rotation, and revocation — see OAuth Applications.API keys
If your integration only ever acts as you, a host of the Network — a script, a scheduled job, a data export — you don’t need an OAuth application. Create an API key under Network Admin > Integrations > Mighty API and send it as a Bearer token, exactly like an access token. A key carries host scopes only, acts as the host who created it, and never expires, so there’s no token exchange, refresh, or/oauth/revoke call; you revoke it from Network Admin. See API Keys for when to choose a key and how to create one.
Endpoints
OAuth endpoints are served from the Network’s community host, not fromapi.mn.co:
Authorization Code flow
The standard flow for user-facing apps. Public clients (mobile, desktop, single-page) must add PKCE; confidential clients (server-side web apps) should use PKCE in addition to their client secret.Step 1 — Redirect to the authorization endpoint
Step 2 — User approves
The user signs in (if they aren’t already) and approves the requested scopes on the consent screen. Mighty redirects back to yourredirect_uri with:
iss parameter on every authorization response, per RFC 9207. Its value matches the issuer in the Network’s /.well-known/oauth-authorization-server metadata. If your client uses more than one authorization server, reject any callback whose iss doesn’t match the server you started the request with.
Step 3 — Exchange the code for an access token
scope field reflects what was actually granted — the intersection of what the application is allowed to request, what the user approved, and what the user is permitted to do in the product. Always check it; don’t assume you got everything you asked for.
Step 4 — Call the Mighty API
Pass the access token as a Bearer token on every GraphQL request:Refreshing tokens
Access tokens are short-lived (expires_in is returned with each token, typically one hour). When a token expires, exchange the refresh token for a new pair:
client_secret. The response shape matches the original token response; the refresh token may rotate, so always persist the new value if one is returned.
Refresh tokens are themselves long-lived but not permanent. They are invalidated when:
- The user revokes the application’s access.
- A host deletes the OAuth application.
- The user changes their password or is signed out network-wide.
- The refresh token reaches its absolute lifetime.
- Your application revokes the token pair at
/oauth/revoke.
invalid_grant, the user must re-authorize — kick them back through Step 1.
Revoking tokens
/oauth/revoke implements RFC 7009 and accepts either an access token or a refresh token in the token parameter. Access and refresh tokens are issued as a pair, so revoking either one revokes both. The caller must be the application the token was issued to: public clients send client_id only, and confidential clients send client_id and client_secret. Call it when the user signs out.
client_secret. The endpoint returns HTTP 200 whether or not the token was valid, as RFC 7009 requires. For when to revoke in each client architecture, see Token handling.
Scopes and permissions
The access token grants exactly the access the underlying user has in the product, intersected with the scopes the user approved.- A
read:networkscope granted to a member only exposes what the member could already see in the product. - A
host:read:network_postsscope is only effective when the authorized user is a host of the Network — a member who approves it still won’t get host-level reads. - The
read:chatsandwrite:chatsscopes expose the member’s private conversations, so they always require the member’s explicit consent — the consent screen cannot be skipped for them.
Host scopes and sign-in
By default, if your authorization request includes any host scope (any scope prefixedhost:), only hosts of the Network can complete sign-in. Members and moderators are blocked at the consent screen and cannot obtain a token.
If your application serves both hosts and members, add require_host=false to the authorization request and ask for the member and host scopes you want in one flow. A host is granted everything requested. A member or moderator signs in normally and is granted only the member scopes, and their consent screen lists only those. Read the scope field of the token response to learn which set the user received.
Only the exact value
false relaxes the requirement. An empty value counts as omitted, and any other value, such as 0 or False, is treated as true.
Errors
OAuth errors follow RFC 6749. The authorization endpoint returns errors via redirect query string; the token endpoint returns them as JSON with a400 (or 401 for client auth failures).
For GraphQL request errors (expired token, missing scope, insufficient permission), see Mighty API error handling.
Security best practices
- Choose an architecture that fits where your code runs. That choice determines the client type, redirect URI, and token storage. See OAuth Client Architectures.
- Use PKCE everywhere. Required for public clients; recommended for confidential clients as defense in depth.
- Always send and validate
state. It’s a required parameter on/oauth/authorize. Generate a cryptographically random, single-use nonce per authorization request, bind it to the user’s session, and reject any callback whosestateis missing or doesn’t match. This is your CSRF defense — skipping it lets an attacker trick a signed-in user into linking the attacker’s authorization code to their account. - Validate
isson the callback. Reject any authorization response whoseissdoesn’t match the Network’sissuer, per RFC 9207. - Pin redirect URIs. Register the exact URIs your app uses. Never register a wildcard, a path you don’t control, or an open redirector.
- Treat the Client Secret like a password. Store it in a secret manager, never in source control, never in a client bundle. Never ship a secret in a mobile, desktop, or single-page app — use the public client type with PKCE instead.
- Request least privilege. Ask for the narrowest scopes that let the feature work. Broader scopes drive higher consent abandonment and expand the blast radius if a token leaks.
- Persist refresh tokens server-side. Refresh tokens are long-lived credentials. Store them encrypted at rest and never expose them to the browser or to logs.
- Replace applications on suspicion of secret leak. Programmatic secret rotation is not currently available. If a secret may have leaked, delete the application (which revokes every token under it) and create a replacement.
Next steps
OAuth Applications
Register, configure, and manage the OAuth applications that issue tokens.
OAuth Client Architectures
Choose an architecture for each client type and avoid the token proxy anti-pattern.
Mighty API
Use your access token against the GraphQL API.