> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flexslot.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth 2.0 Overview

> Build third-party integrations that act on behalf of Flexslot users

<Note>
  **New partner?** OAuth requires a registered partner row. [Apply for partner access](https://flexslot.gg/developers/apply) first, then come back here to wire your client.
</Note>

## What is OAuth at Flexslot?

OAuth 2.0 is how third-party apps act **on behalf of a Flexslot user** without ever seeing that user's password. Your app sends the user to `flexslot.gg`, the user clicks "Allow", and you get back an access token scoped to exactly what you asked for.

If you're building a deck tracker, a tournament platform, a Discord bot, a metagame analyzer, or any tool that needs to read or write a user's decks, sideboard guides, or strategy content, OAuth is what you want.

<CardGroup cols={2}>
  <Card title="Claude Code Skill" icon="sparkles" href="/oauth/claude-code-skill">
    Let Claude Code build your integration for you
  </Card>

  <Card title="Quickstart" icon="rocket" href="/oauth/quickstart">
    Get your first integration working in 10 minutes
  </Card>

  <Card title="Code samples" icon="code" href="/oauth/code-samples">
    Drop-in Node.js, Python, and curl examples
  </Card>

  <Card title="Authorization Code Flow" icon="diagram-project" href="/oauth/authorization-code-flow">
    The full end-to-end flow with PKCE
  </Card>

  <Card title="Scopes" icon="list-check" href="/oauth/scopes">
    Every scope and what it grants
  </Card>

  <Card title="OpenAPI spec" icon="file-code" href="https://docs.flexslot.gg/openapi.json">
    Pull the schema into your codegen — [JSON](https://docs.flexslot.gg/openapi.json) · [YAML](https://docs.flexslot.gg/openapi.yaml)
  </Card>
</CardGroup>

## Which auth method should I use?

Flexslot supports three ways for an external system to authenticate. Pick the one that matches your situation, not the one that's easiest to ship.

| Method                          | Acts as                                       | Use when                                                                                | Don't use when                                                |
| ------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| **OAuth 2.0**                   | A specific Flexslot user (with their consent) | Your product is used by multiple Flexslot users and each one connects their own account | You need server-to-server access that isn't tied to a user    |
| **Personal Access Token (PAT)** | A single user (yourself)                      | You're scripting against your own account or running a one-off integration              | You're building a product other Flexslot users will sign into |
| **HMAC Webhook Signing**        | Flexslot itself (verifying *us*)              | Receiving webhook callbacks from Flexslot                                               | Calling our API                                               |

<Note>
  If you're not sure: **use OAuth**. PATs are only appropriate for personal scripts; HMAC is only for verifying inbound webhooks. Everything else is OAuth.
</Note>

## Terminology

A few terms you'll see throughout these docs. We use the standard OAuth 2.0 vocabulary from [RFC 6749](https://www.rfc-editor.org/rfc/rfc6749).

<AccordionGroup>
  <Accordion title="Resource Owner" icon="user">
    The Flexslot user whose decks, guides, or content your app wants to access. They're the one clicking "Allow" on the consent screen.
  </Accordion>

  <Accordion title="Client" icon="laptop-code">
    Your application. Registered with Flexslot via the partner admin and identified by a `client_id`.
  </Accordion>

  <Accordion title="Authorization Server" icon="server">
    Flexslot. Specifically the endpoints under `https://api.flexslot.gg/api/public/v1/oauth/`.
  </Accordion>

  <Accordion title="Resource Server" icon="database">
    Flexslot's REST API at `https://api.flexslot.gg/api/public/v1/...`. Accepts the access tokens issued by the authorization server.
  </Accordion>

  <Accordion title="Access Token" icon="key">
    A short-lived (1 hour) opaque string that proves your app is acting on behalf of a user. Sent as `Authorization: Bearer <token>`.
  </Accordion>

  <Accordion title="Refresh Token" icon="rotate">
    A longer-lived token used to get a new access token when the current one expires. **Rotates** on every use — store the new one.
  </Accordion>

  <Accordion title="Scope" icon="list-check">
    A space-separated list of permissions your app requests, e.g. `decks:read sideboards:write`. The user sees these on the consent screen.
  </Accordion>

  <Accordion title="PKCE" icon="shield-halved">
    Proof Key for Code Exchange. A required security mechanism that binds the authorization code to your app, even if the code is intercepted. Mandatory for all clients.
  </Accordion>
</AccordionGroup>

## Endpoints

The API endpoints (token, introspection, revocation) live under `https://api.flexslot.gg`. The **authorization endpoint** — the only one a browser navigates to — is the user-facing consent screen at `https://flexslot.gg/oauth/authorize`. We publish a [discovery document](https://api.flexslot.gg/.well-known/oauth-authorization-server) ([RFC 8414](https://www.rfc-editor.org/rfc/rfc8414)) listing the exact URLs; fetch it programmatically rather than hard-coding hosts.

| Endpoint      | URL                                                              | Purpose                                                                                   |
| ------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Discovery     | `https://api.flexslot.gg/.well-known/oauth-authorization-server` | Lists all endpoints and supported capabilities                                            |
| Authorization | `https://flexslot.gg/oauth/authorize`                            | Where you send the user's browser to consent                                              |
| Token         | `https://api.flexslot.gg/api/public/v1/oauth/token`              | Exchange code for tokens, or refresh tokens                                               |
| Introspection | `https://api.flexslot.gg/api/public/v1/oauth/introspect`         | Check whether a token is still valid ([RFC 7662](https://www.rfc-editor.org/rfc/rfc7662)) |
| Revocation    | `https://api.flexslot.gg/api/public/v1/oauth/revoke`             | Revoke a token on logout ([RFC 7009](https://www.rfc-editor.org/rfc/rfc7009))             |

<Note>
  The authorization endpoint is on `flexslot.gg`, not `api.flexslot.gg` — it's a web page the user's browser opens, not an API call. The `iss` value returned on the callback is still the API issuer `https://api.flexslot.gg`; validate against that.
</Note>

## What's supported

| Capability                       | Supported    | Notes                                                            |
| -------------------------------- | ------------ | ---------------------------------------------------------------- |
| Authorization Code Grant         | Yes          | The only user-facing grant we support                            |
| PKCE (S256)                      | **Required** | All clients, public and confidential                             |
| Refresh Token Rotation           | Yes          | New refresh token on every refresh                               |
| Token Introspection              | Yes          | RFC 7662                                                         |
| Token Revocation                 | Yes          | RFC 7009                                                         |
| Sender-Constrained Tokens (DPoP) | Yes (opt-in) | See [DPoP](/oauth/dpop)                                          |
| Client Credentials Grant         | No           | Use a PAT instead                                                |
| Implicit Grant                   | **No**       | Deprecated by [RFC 9700](https://www.rfc-editor.org/rfc/rfc9700) |
| Resource Owner Password Grant    | **No**       | Forbidden by RFC 9700                                            |
| Device Authorization Grant       | No           | Not currently supported                                          |

## Token lifetimes

| Token              | Lifetime   | Rotates?                           |
| ------------------ | ---------- | ---------------------------------- |
| Authorization code | 10 minutes | Single use                         |
| Access token       | 1 hour     | No (request a new one via refresh) |
| Refresh token      | 30 days    | **Yes — every use**                |

<Warning>
  Refresh tokens rotate. Every time you call `/token` with `grant_type=refresh_token`, you get back a new refresh token and the old one is invalidated. Store the new one immediately. Replaying an old refresh token revokes the entire grant. See [Security](/oauth/security#refresh-token-rotation).
</Warning>

## Where to go next

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/oauth/quickstart">
    Register a client and run the flow with curl
  </Card>

  <Card title="Security best practices" icon="shield" href="/oauth/security">
    PKCE, state, redirect URIs, refresh rotation
  </Card>

  <Card title="Error reference" icon="circle-exclamation" href="/oauth/errors">
    Every error code and how to fix it
  </Card>

  <Card title="Migrating from PAT" icon="arrow-right-arrow-left" href="/oauth/migration-from-pat">
    Already using a PAT? Add OAuth alongside.
  </Card>
</CardGroup>
