Authentication
API key header
Send your key on every request:
XF-Api-Key: <your-api-key>
That is all a server-to-server or game-client integration needs. The key already carries its scopes and its game restriction.
Acting as a specific user (optional)
Only needed if you act as a forum user - e.g. letting a logged-in player post a review through your client. Add:
XF-Api-User: <user_id>
For read-only mod browsing you do not need it.
Scope behavior
- A key bound to one or more games is game-scoped: every list is auto-filtered to those games, and a direct lookup of an out-of-scope record returns 403.
- A key bound to zero games is unrestricted - the mod-manager / launcher tier, browsing all public games.
You never pass a game_id to "pick" a game. Scope is enforced server-side.
NSFW exclusion
If a game is flagged to exclude NSFW from API/in-game access (the default), the API never returns NSFW-marked mods for it, on any key tier. The website still shows them behind its own adult gate - the API surface is the compliance-safe subset. This is a per-game setting, not something the key toggles.
Keep your key safe
Do not ship the raw key in plaintext inside a distributable client where it can be extracted. See Ownership & anti-piracy.
Player login/register in a launcher (OAuth2)
XF-Api-Key is for your server or client acting as itself - browsing, listing, downloading. It has no concept of "a player logging in." If your launcher needs a real player to sign in (or register a new account) and then act as themselves - post a review, favorite a mod, see their own library - use OAuth2 instead. Do not try to fake this with XF-Api-User: that header only works on a super-user key and lets the key impersonate any account by ID with no login step at all, which is not a login flow and not safe to ship in a client.
1. Register your client (one-time, ask a site admin)
An admin creates an OAuth2 client in the AdminCP (Applications > OAuth Clients), giving you:
client_id- a
redirect_uri(orredirect_urischeme) your launcher listens on, e.g.ayakamods-launcher://oauth/callbackorhttp://127.0.0.1:PORT/callbackfor a local-loopback listener - a client type: Public for a launcher/desktop app (recommended - a distributed binary cannot keep a secret), Confidential only if the token exchange happens on a server you control
Public clients must use PKCE (below) since they have no client_secret.
2. Send the player to authorize
Open the system browser (not an embedded webview, so the player's existing session/password manager works) to:
https://ayakamods.com/oauth2?client_id=YOUR_CLIENT_ID
&response_type=code
&redirect_uri=YOUR_REDIRECT_URI
&scope=mod:read+mod_rating:read
&state=RANDOM_STRING
&code_challenge=CODE_CHALLENGE
&code_challenge_method=S256
If the player isn't logged in, XenForo shows its normal login and register page first, then the consent screen, then redirects back to your redirect_uri with a code. This is the whole point - AyakaMods doesn't need its own login/register API, XenForo's is reused as-is.
PKCE (code_verifier / code_challenge): generate a random code_verifier, send code_challenge = base64url(sha256(code_verifier)) here, and send the raw code_verifier in the token exchange below. Required for public clients.
3. Exchange the code for a token
curl https://ayakamods.com/api/oauth2/token \
-d grant_type=authorization_code \
-d client_id=YOUR_CLIENT_ID \
-d code=THE_CODE_FROM_STEP_2 \
-d redirect_uri=YOUR_REDIRECT_URI \
-d code_verifier=YOUR_CODE_VERIFIER
Response:
{
"access_token": "...",
"refresh_token": "...",
"token_type": "bearer",
"expires_in": 3600,
"scope": "mod:read mod_rating:read"
}
4. Call the API as that player
curl https://ayakamods.com/api/mods/ \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
No XF-Api-Key needed on these calls - the Bearer token identifies the player directly, and normal site permissions apply to them. When access_token expires, use grant_type=refresh_token with your refresh_token to get a new pair without asking the player to log in again.
Note on game scoping: OAuth tokens act as the logged-in player, not as a developer's game-restricted key - they are not narrowed to your game the way an XF-Api-Key is. Use OAuth only for player-identity actions (login, reviews, favorites); keep using your game-scoped XF-Api-Key for everything else (listing/downloading your game's mods).