Skip to main content
The Authorization Code Grant with PKCE is the only user-facing grant Flexslot supports. This page is the complete reference: every parameter, every header, every status code.

The flow at a glance

Why PKCE?

Without PKCE, anyone who intercepts the authorization code (browser history, server logs, a malicious app handling your custom URL scheme) can exchange it for tokens. PKCE binds the code to a secret your client generated before the flow started.
  • Your client generates code_verifier — a random 43-128 character string.
  • Your client sends code_challenge = BASE64URL(SHA256(code_verifier)) to /authorize.
  • Flexslot stores the challenge against the issued code.
  • When your client redeems the code at /token, it sends the original code_verifier.
  • Flexslot recomputes SHA256(code_verifier) and compares to the stored challenge.
If the values don’t match, you get invalid_grant and the code is invalidated. See RFC 7636 for the spec.
code_challenge_method=plain is forbidden at Flexslot. Use S256 only. RFC 9700 deprecates plain because it provides no actual protection.

Generating PKCE values

Step 1 — Authorization request

Send the user’s browser to the consent screen on the Flexslot web app:
This is flexslot.gg, not api.flexslot.gg. The authorization endpoint is a web page the user’s browser opens — pointing the browser at the API host returns 401 FLEXSLOT_AUTHENTICATION_REQUIRED. Only the token, introspection, and revocation endpoints live on api.flexslot.gg.

Required query parameters

Example

All query parameter values must be percent-encoded. Use your language’s URL builder — don’t hand-roll the string.

Step 2 — User consents

Flexslot renders the consent screen, showing the user:
  • Your application’s name and logo (from the partner admin)
  • The scopes you requested, in human-readable form
  • A clear Allow and Deny option
If the user clicks Allow, you get redirected with a code. If they click Deny, you get redirected with error=access_denied.

Step 3 — Callback to your redirect_uri

What you must verify

1

state matches

Compare to the value you stored when starting the flow. If it doesn’t match, abort — this is a CSRF attempt.
2

iss equals https://api.flexslot.gg

RFC 9207 mix-up defense. If a different iss shows up, you’ve been redirected to the wrong AS.
3

No error parameter

If error=... is present, the flow failed. See errors.

Step 4 — Token exchange

Body parameters

Authentication

Example request

Success response

200 OK, Content-Type: application/json, Cache-Control: no-store:

Error response

400 Bad Request (or 401 for invalid_client), Content-Type: application/json:
See Errors for the full catalog.

Step 5 — Call the API

The resource server is game-scoped: deck, guide, and card endpoints live under /api/public/v1/games/{game}/..., where {game} is the game’s exact slug (for Magic, magic-the-gathering). There is no bare /api/public/v1/decks/ — it returns 404. The slug is the game field on any deck or guide you read back.
The resource server returns the canonical Flexslot JSON envelope ({ "error", "message", "details" }) on auth/scope failures — it does not emit an RFC 6750 WWW-Authenticate: Bearer challenge. A token lacking the required scope returns 403 Forbidden:
An expired, revoked, or unknown token returns 401 Unauthorized with the matching error code:
The only resource-server response carrying a WWW-Authenticate header is the DPoP lane (Authorization: DPoP …), which on proof failure returns 401 with WWW-Authenticate: DPoP error="invalid_dpop_proof".

Step 6 — Refresh

When the access token expires (or proactively, ~5 minutes before it does), exchange the refresh token for a new pair:
The response shape is identical to the initial exchange — and includes a new refresh token. Store the new one. The old one is now invalid.
Refresh tokens rotate. If you replay a refresh token after it’s been used, Flexslot revokes the entire grant. The user will have to re-consent. See Security → Refresh token rotation.

Common gotchas

Code samples

Full Express, Flask, and curl implementations

Security

PKCE, state, redirect URIs in depth

Errors

Every error code explained

DPoP

Sender-constrained tokens