> ## 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.

# Managing OAuth Clients

> Create, rotate, and revoke your OAuth2 clients without admin intervention

Once your partner application is approved, you manage your own OAuth2 clients — no Flexslot admin in the loop. A client is the credential your app uses to start the authorization code flow: a `client_id`, an optional `client_secret`, a set of redirect URIs, and the scopes the client may request.

You can manage clients two ways:

<CardGroup cols={2}>
  <Card title="From the dashboard" icon="browser">
    **Account → API access** at [flexslot.gg/account?section=api-access](https://flexslot.gg/account?section=api-access). The **OAuth applications** card lets you point-and-click create, rotate, and revoke.
  </Card>

  <Card title="Programmatically" icon="terminal">
    The `me/partner/oauth2-clients` endpoints, authenticated with a Personal Access Token. For scripts and CI.
  </Card>
</CardGroup>

Both paths share the same rules and the same one-time-secret behavior.

## Confidential vs public clients

<Steps>
  <Step title="Confidential">
    Runs on a server you control. Gets a `client_secret`, shown **once** at creation. Sends the secret to the token endpoint via HTTP Basic auth. Choose this for a backend web app.
  </Step>

  <Step title="Public">
    Runs where you can't keep a secret — a CLI, native app, or SPA. Gets **no** secret; security comes entirely from PKCE. Choose this for anything that ships to the user's device or browser.
  </Step>
</Steps>

PKCE is mandatory for both types ([RFC 9700](https://www.rfc-editor.org/rfc/rfc9700)). The client type only decides whether a secret exists.

## Redirect URI rules

Every redirect URI is validated at creation **and on every edit**. The rules are the same exact-match rules the authorization endpoint enforces:

* HTTPS is required for every non-loopback URI.
* HTTP is allowed **only** for the loopback hosts `localhost`, `127.0.0.1`, and `[::1]` (native-app loopback per [RFC 8252](https://www.rfc-editor.org/rfc/rfc8252)). The port is unconstrained.
* No wildcards (`*`) anywhere in the URI.
* No URL fragments (`#...`).
* Custom native-app schemes (`com.example.app://`) are not accepted — native apps use a loopback redirect.

<Warning>
  Redirect URIs are matched byte-for-byte at `/authorize`. Register every environment's callback explicitly — a trailing slash or port mismatch is a different URI.
</Warning>

## From the dashboard

<Steps>
  <Step title="Open Account → API access">
    The **OAuth applications** card lists your existing clients and a **New application** button.
  </Step>

  <Step title="Create a client">
    Enter a name, pick **Confidential** or **Public**, add one redirect URI per line, and check the scopes the client may request. Click **Create application**.
  </Step>

  <Step title="Copy the secret (confidential only)">
    A confidential client shows its `client_secret` once. Copy it immediately — it is never shown again.
  </Step>

  <Step title="Edit a client later">
    Open a client to change its **name**, **redirect URIs**, **requested scopes**, branding URLs (application/privacy/terms), or its **DPoP** setting. Edits are partial — only the fields you change are touched — and the same validation applies as at creation (redirect URIs must be HTTPS or `http` loopback with no wildcards/fragments; scopes must be from the published scope universe). Editing does **not** rotate the secret or invalidate existing tokens. You don't have to get redirect URIs and scopes perfect up front — add the next environment's callback or widen scopes here whenever you need to.
  </Step>

  <Step title="Rotate or revoke later">
    Each client has **Rotate secret** (confidential only) and **Revoke** actions. Rotating invalidates the old secret immediately; revoking disables the client and signs out every user who authorized it.
  </Step>
</Steps>

## Programmatically (Personal Access Token)

Mint a Personal Access Token from **Settings → Personal Access Tokens**, then call the management endpoints with it as a bearer token. These live under `/api/public/v1/me/partner/oauth2-clients` and resolve the partner from the token's owner.

<CodeGroup>
  ```bash List clients theme={null}
  curl -sS https://api.flexslot.gg/api/public/v1/me/partner/oauth2-clients \
    -H "Authorization: Bearer $FLEXSLOT_PAT"
  ```

  ```bash Create a confidential client theme={null}
  curl -sS -X POST https://api.flexslot.gg/api/public/v1/me/partner/oauth2-clients \
    -H "Authorization: Bearer $FLEXSLOT_PAT" \
    -H "Content-Type: application/json" \
    -d '{
      "application_name": "My Integration",
      "client_type": "confidential",
      "redirect_uris": ["https://app.example.com/oauth/callback"],
      "allowed_scopes": ["decks:read"]
    }'
  ```

  ```bash Rotate a secret theme={null}
  curl -sS -X POST \
    https://api.flexslot.gg/api/public/v1/me/partner/oauth2-clients/$CLIENT_ID/rotate-secret \
    -H "Authorization: Bearer $FLEXSLOT_PAT"
  ```

  ```bash Revoke a client theme={null}
  curl -sS -X DELETE \
    https://api.flexslot.gg/api/public/v1/me/partner/oauth2-clients/$CLIENT_ID \
    -H "Authorization: Bearer $FLEXSLOT_PAT"
  ```
</CodeGroup>

<Note>
  The PAT-authenticated API covers list, create, rotate-secret, and revoke. **Editing a client's configuration** (redirect URIs, scopes, metadata) is currently done from the **dashboard** (Account → API access) — there is no public `PATCH` endpoint for it yet. Create, rotate, and revoke are the same operations either way.
</Note>

A create or rotate response returns the client plus the one-time secret:

```json theme={null}
{
  "client": {
    "client_id": "flx_client_01HX2K…",
    "client_type": "confidential",
    "application_name": "My Integration",
    "redirect_uris": ["https://app.example.com/oauth/callback"],
    "allowed_scopes": ["decks:read"],
    "status": "active"
  },
  "plaintext_client_secret": "flx_cs_01HX2K…",
  "secret_rotated_at": "2026-06-02T18:00:00Z"
}
```

For a public client, `plaintext_client_secret` is an empty string — there is no secret to copy.

## Revocation is a cascade

Revoking a client is not just a status flip. It also revokes every grant and every access and refresh token issued under that client. Any user who authorized the client is signed out, and bearer tokens that client minted stop working immediately. This is deliberate: a status-only revoke would leave live tokens that the resource server still honors.

Revoked clients are retained for audit but disappear from both the dashboard list and the API list.

## Client limit

Each partner may hold up to **10** active clients (active or suspended count toward the limit; revoked clients do not). Revoke a client you no longer use to free a slot. If you need a higher limit, contact Flexslot.

## Next steps

<CardGroup cols={2}>
  <Card title="OAuth Quickstart" icon="rocket" href="/oauth/quickstart">
    Use a client you just created to get an access token
  </Card>

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