Skip to main content

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.

This header only works on a super-user key, which can act as any account. Super-user keys are never issued for distributable clients (tools, launchers, game builds). If a player needs to act as themselves, use OAuth2 (below).

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​

How careful you need to be depends on where the key lives:

  • On a server you control (your backend, a proxy): keep it in an environment variable or secret store, never in a public repo.
  • Inside a distributable client (a desktop tool, a launcher, a game build): assume anyone can extract it. Keys for distributable clients are therefore read-only: they carry only read scopes, so an extracted key cannot post, edit or delete anything. Tool keys (mod managers, update checkers) are Guest keys that see exactly what a logged-out visitor sees.
  • A key can be revoked and replaced at any time. If yours leaks or gets abused, contact us and we rotate it.
  • Never ship a super-user key, or any key with write scopes, in something you distribute.

If you want the key out of the binary entirely, run a small proxy server that holds the key and have your client call the proxy. See also 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 (Setup > Service providers > OAuth2 clients), giving you:

  • client_id
  • a redirect_uri your launcher listens on. It must be http or https; custom schemes such as myapp://callback are rejected. For a desktop app, use a local loopback listener such as http://127.0.0.1/callback: on 127.0.0.1 (and [::1]) any port matches the registered URI, so you can bind a free port at runtime. This does not apply to localhost, which must match the registered port exactly.
  • 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/authorize?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.

5. Signing out​

Public clients cannot call the token revoke, introspect or info endpoints, because those require a client_secret. To sign a player out, delete the stored access and refresh tokens on the device. Access tokens expire on their own after expires_in seconds (3600).

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