Authentication
The Spellweave API uses OAuth 2.0 with Authorization Code + PKCE to securely access user data. This guide covers the full authentication flow.
Overview
Your app redirects users to Spellweave to authorize access. After approval, your app receives an authorization code that you exchange for access and refresh tokens.
- Your app generates a PKCE code verifier and challenge
- User is redirected to Spellweave to log in and consent
- Spellweave redirects back with an authorization code
- Your server exchanges the code for tokens
- Use the access token to call the API
PKCE (Proof Key for Code Exchange)
PKCE is required on all authorization requests. It prevents authorization code interception attacks. Only the S256 method is supported.
// 1. Generate a random code_verifier (43-128 characters)
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const codeVerifier = btoa(String.fromCharCode(...array))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
// 2. Create the code_challenge (SHA-256 hash, base64url-encoded)
const encoder = new TextEncoder();
const digest = await crypto.subtle.digest("SHA-256", encoder.encode(codeVerifier));
const codeChallenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");Authorization Request
Redirect the user to the authorization endpoint with these parameters:
| Parameter | Required | Description |
|---|---|---|
response_type | Yes | Must be "code" |
client_id | Yes | Your app's client ID |
redirect_uri | Yes | Must match a registered redirect URI exactly |
scope | Yes | Space-separated list of scopes |
code_challenge | Yes | S256-hashed PKCE code verifier |
code_challenge_method | Yes | Must be "S256" |
state | No | Random string for CSRF protection (recommended) |
GET https://public-api.spellweave.app/api/v1/oauth/authorize
?response_type=code
&client_id=sw_abc123...
&redirect_uri=https://yourapp.com/callback
&scope=profile:read collections:read decks:read
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
&state=random_csrf_stringToken Exchange
After the user approves, they are redirected to your redirect_uri with a code parameter. Exchange it for tokens using a server-side POST:
curl -X POST https://public-api.spellweave.app/api/v1/oauth/token \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://yourapp.com/callback" \
-d "code_verifier=YOUR_ORIGINAL_CODE_VERIFIER"{
"access_token": "eyJhbG...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBh...",
"scope": "profile:read collections:read decks:read"
}Using the Access Token
Include the access token in the Authorization header:
curl https://public-api.spellweave.app/api/v1/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Refreshing Tokens
Access tokens expire after 1 hour. Use the refresh token to get a new pair without re-prompting the user. Each refresh token is single-use. A new refresh token is returned with every exchange.
curl -X POST https://public-api.spellweave.app/api/v1/oauth/token \
-d "grant_type=refresh_token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "refresh_token=YOUR_REFRESH_TOKEN"Revoking Tokens
Revoke a token when the user logs out of your app or disconnects their Spellweave account:
curl -X POST https://public-api.spellweave.app/api/v1/oauth/revoke \
-d "token=TOKEN_TO_REVOKE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"