Developer Portal
Eksperimental Aktibo pang dine-develop ang bot at app platform. Na-ship ang suporta para sa self-hosted servers noong 2026-08-13, pero mas kaunti ang features nito kumpara sa cloud. Tingnan kung ano ang supported.
← Docs

Log in with GameVox

Hayaang mag-sign in ang mga tao sa website o app mo gamit ang GameVox account nila. Ito ang standard na OAuth2 authorization-code flow, kahugis ng sa Discord, at hindi ito nangangailangan ng bot: humihingi ang app mo ng ilang bahagi ng account ng user, inaaprubahan ito ng user, at nakakakuha ng token ang backend mo.

Para saan ito

  • Sign-in at account linking. Alamin kung sino ang user (isang stable na GameVox user ID, username, avatar) at, kung papayag sila, ang verified email nila.
  • Server pickers at dashboards. Gamit ang guilds, makikita mo kung aling servers kasali ang user at kung saan nila puwedeng i-manage ang settings.
  • Hindi ito para kumilos bilang user. Hindi makakapagpadala ng messages, makakasali sa voice, o makakapagbago ng kahit ano sa GameVox ang isang user token. Kailangan ng bot para sa anumang kumikilos sa loob ng GameVox.

Bago ka magsimula

  1. Gumawa ng application sa developers.gamevox.com. Ang Client ID sa OAuth2 tab nito ang client_id mo.
  2. Sa OAuth2 tab, idagdag ang bawat redirect URI na gagamitin ng app mo (hanggang 10). Dapat https:// ang mga ito, o http://localhost / http://127.0.0.1 para sa development, at walang #fragment. Dapat eksaktong tugma ang ipapadala mong redirect_uri sa isa sa mga ito, kasama ang query string.
  3. Kopyahin ang client secret. Isang beses lang ito ipinapakita, kapag ginawa ang app o ni-reset ang secret. Itago ito sa backend mo: kailangan ito ng bawat token request.

Endpoints

GET  https://gamevox.com/oauth2/authorize/
POST https://app-api.gamevox.com/api/oauth2/token
POST https://app-api.gamevox.com/api/oauth2/token/revoke
GET  https://app-api.gamevox.com/api/users/@me
GET  https://app-api.gamevox.com/api/users/@me/guilds
GET  https://app-api.gamevox.com/api/oauth2/@me
PUT  https://api.gamevox.com/api/users/@me/applications/{application.id}/role-connection

Huwag tanggalin ang trailing slash sa /oauth2/authorize/. Sumasagot din ang token at user endpoints sa ilalim ng /api/v10/, kaya gumagana nang walang binabago ang mga library na naglalagay ng version sa path. Nasa api.gamevox.com ang role connections, hindi sa app-api.

1. Ipadala ang user sa GameVox

I-redirect ang browser (normal na navigation, hindi popup o iframe) sa authorize URL:

https://gamevox.com/oauth2/authorize/
  ?response_type=code
  &client_id=123456789012345678
  &scope=identify%20email
  &redirect_uri=https%3A%2F%2Fyourapp.example.com%2Fauth%2Fgamevox
  &state=Zx81kq0vT2
ParameterKailanganPaglalarawan
response_type Oo Palaging code.
client_id Oo Ang Client ID sa OAuth2 tab ng app mo.
scope Oo Hiwalay sa space (URL-encoded bilang %20 o +). Tingnan ang Scopes. Huwag isama ang bot: kapag may bot, nagiging server install ang URL na ito.
redirect_uri Oo Isa sa registered redirect URIs mo, eksaktong pareho.
state Hindi Isang value na hindi mahuhulaan at nakatali sa session ng user (hanggang 1024 characters). Bumabalik ito nang walang pagbabago; i-check ito para mapigilan ang cross-site request forgery.
code_challenge Hindi Optional na PKCE challenge, 43 hanggang 128 characters.
code_challenge_method Hindi S256 kapag nagpapadala ka ng challenge. Tinatanggihan ang plain.
prompt Hindi Nilalaktawan ng none ang consent screen kapag naaprubahan na ng user ang app mo para sa lahat ng scopes na ito. Itatanong pa rin ang anumang bago.

Ang nakikita ng user

  • Isang consent screen sa gamevox.com na may pangalan, icon at paglalarawan ng app mo, ang account na naka-sign in sila, isang simpleng listahan ng mga makikita mo, at ang site na pupuntahan nila.
  • Kung naka-sign out sila, dadalhin sila ng Log in sa GameVox web app at diretsong ibabalik sa parehong screen.
  • Lalabas sa ilalim ng mga button ang Terms of Service at Privacy Policy links mo kapag na-set mo ang mga ito sa Pangkalahatang Impormasyon tab.

2. I-handle ang callback

Pagka-click ng user sa Authorize, ipapadala sila ng GameVox sa redirect URI mo kasama ang isang code:

https://yourapp.example.com/auth/gamevox?code=3vR0b...&state=Zx81kq0vT2

Kung Cancel ang i-click nila:

https://yourapp.example.com/auth/gamevox?error=access_denied
  &error_description=The+user+denied+the+request&state=Zx81kq0vT2
  • I-reject ang callback kung hindi tugma ang state sa in-issue mo para sa browser na ito.
  • Nag-e-expire ang code pagkalipas ng 10 minuto at isang beses lang ito gumagana. I-exchange ito agad, mula sa backend mo.

3. I-exchange ang code para sa tokens

Mula sa backend mo, mag-POST ng form-encoded na body (application/x-www-form-urlencoded, hindi JSON) sa token endpoint:

curl -X POST https://app-api.gamevox.com/api/oauth2/token \
  -u "123456789012345678:CS.your-client-secret" \
  -d grant_type=authorization_code \
  -d code=3vR0b... \
  -d redirect_uri=https://yourapp.example.com/auth/gamevox
{
  "access_token": "GVO.mJ4c...",
  "token_type": "Bearer",
  "expires_in": 604800,
  "refresh_token": "GVR.9tQe...",
  "scope": "identify email"
}
  • Mag-authenticate gamit ang HTTP Basic (client_id:client_secret) gaya sa itaas, o ipadala ang client_id at client_secret bilang form fields.
  • Dapat pareho ang redirect_uri sa value na ipinadala mo sa step 1. Idagdag ang code_verifier kung gumamit ka ng PKCE.
  • May Cache-Control: no-store ang mga response. Huwag kailanman ilagay ang client secret o tokens sa browser code o sa URLs.

4. Tawagin ang API

Ipadala ang access token bilang Authorization: Bearer. Kailangan ng GET /users/@me ang identify scope:

curl https://app-api.gamevox.com/api/users/@me \
  -H "Authorization: Bearer GVO.mJ4c..."
{
  "id": "1557709980780474368",
  "gamevox_id": "edf412bc-a7b8-4f2a-a810-8b9eb8c02462",
  "username": "alice",
  "discriminator": "0",
  "global_name": "alice",
  "avatar": null,
  "gamevox_avatar_url": "https://...",
  "email": "alice@example.com",
  "verified": true
}
  • Ang id ay ang stable na GameVox ID ng user. Dito i-key ang account records mo; puwedeng magbago ang usernames. Ang gamevox_id ay ang parehong user sa native UUID form ng GameVox.
  • Kasama lang ang email at verified kapag may email scope, at kung may email na naka-file ang user. Verified addresses lang ang sine-save ng GameVox, kaya palaging true ang verified kapag naka-set ang email.
  • Palaging null ang avatar (gagawa kasi ng Discord CDN link mula rito ang Discord libraries). Gamitin ang gamevox_avatar_url, na wala sa response kapag walang picture ang user.

Ang servers ng user

Kailangan ng GET /users/@me/guilds ang guilds scope:

[
  { "id": "1557445672742031360", "name": "Raid Night", "icon": null,
    "owner": true,  "permissions": "2251799813685247", "features": [] },
  { "id": "1557445672742031361", "name": "Guild Hall", "icon": null,
    "owner": false, "permissions": "1056", "features": [] }
]
  • Summary para sa pagpili ng server ang permissions, hindi buong kalkulasyon: lahat ng bit (kasama ang ADMINISTRATOR) para sa owner at admins, MANAGE_GUILD (32) at VIEW_CHANNEL (1024) kung saan puwedeng i-edit ng user ang server settings, at VIEW_CHANNEL para sa lahat ng iba pa.
  • Hanggang limit na server kada response (1 hanggang 200, default 200), pinakaluma muna. Mag-page gamit ang after o before na naka-set sa id ng isang server mula sa naunang page, gaya sa Discord.

Ang kasalukuyang authorization

Gumagana ang GET /oauth2/@me sa kahit anong scope at sinasabi nito kung aling app ang may-ari ng token, ano ang ibinigay dito, at kailan ito mag-e-expire. Kasama ang user kapag may identify.

{
  "application": { "id": "123456789012345678", "name": "RaidPlanner", ... },
  "scopes": ["identify", "email"],
  "expires": "2026-10-15T15:03:20Z",
  "user": { "id": "1557709980780474368", "username": "alice", ... }
}

Linked roles

Gamit ang role_connections.write, puwede mong i-record kung aling account ang meron ang user sa panig mo. Pansinin ang host: api.gamevox.com.

curl -X PUT \
  https://api.gamevox.com/api/users/@me/applications/123456789012345678/role-connection \
  -H "Authorization: Bearer GVO.mJ4c..." \
  -H "Content-Type: application/json" \
  -d '{"platform_name": "RaidPlanner", "platform_username": "ShadowMage", "metadata": {}}'

Makikita ito ng user sa ilalim ng Settings > Authorized Apps bilang “Linked as ShadowMage on RaidPlanner”. Dapat ang metadata keys ay mga key na dinefine mo sa role-connection metadata ng app mo. Binabasa itong muli ng GET sa parehong URL.

Pag-refresh

Tumatagal nang 7 araw ang access tokens (in seconds ang expires_in). Kumuha ng bagong pair gamit ang refresh token:

curl -X POST https://app-api.gamevox.com/api/oauth2/token \
  -u "123456789012345678:CS.your-client-secret" \
  -d grant_type=refresh_token \
  -d refresh_token=GVR.9tQe...
  • Nagro-rotate ang refresh tokens. May bagong refresh token sa response, at agad na hindi na gagana ang lumang refresh token at ang access token nito, kaya i-save muna ang bagong pair bago ito gamitin.
  • Puwede kang magpadala ng scope para limitahan ang bagong token sa mas kaunting scopes. Kapag humingi ka ng scope na hindi kailanman ibinigay ng user, magfe-fail ito nang may invalid_scope.
  • Nag-e-expire ang hindi nagagamit na refresh token pagkalipas ng 90 araw. Hanggang 25 live token pairs lang kada app ang puwede sa bawat user; kapag gumawa ng ika-26, tatanggalin ang pinakaluma.

Pag-revoke (pag-log out)

Mag-revoke kapag nag-sign out ang user sa app mo. Nire-revoke ng alinmang token sa pair ang buong pair. Palaging sumasagot ng 200 ang endpoint para sa valid na client, umiiral man o hindi ang token.

curl -X POST https://app-api.gamevox.com/api/oauth2/token/revoke \
  -u "123456789012345678:CS.your-client-secret" \
  -d token=GVO.mJ4c...

PKCE

Optional, at inirerekomenda kung puwedeng mabuo ang authorize URL sa lugar na makikita ng iba. S256 lang ang suportado ng GameVox, at kailangan pa rin ng token request ang client secret mo: walang public clients na walang secret.

// Before redirecting: keep the verifier with the user's pending login.
const verifier = base64url(crypto.randomBytes(32));
const challenge = base64url(crypto.createHash('sha256').update(verifier).digest());
// authorize URL: ...&code_challenge=CHALLENGE&code_challenge_method=S256
// token request: ...&code_verifier=VERIFIER (client secret still required)

Scopes

ScopeAng puwedeng gawin ng app mo
identify Basahin ang ID, username at avatar ng user: GET /users/@me, at user sa GET /oauth2/@me.
email Idagdag ang verified email ng user sa /users/@me.
guilds Basahin ang server list ng user: GET /users/@me/guilds.
role_connections.write Basahin at isulat ang linked role details ng user para sa app mo.

Ang anumang ibang scope, pati ang connections, guilds.join at applications.commands na walang bot, ay tinatanggihan sa consent screen na may mensaheng nagsasabi nito.

Errors

Sumasagot ang token at revoke endpoints ng errors sa standard na OAuth2 shape, {"error": "...", "error_description": "..."}, kaya nababasa ito ng OAuth libraries nang walang binabago:

errorHTTPKahulugan
invalid_client 401 Maling client ID o secret, na-delete na app, o naka-suspend ang account ng owner ng app.
invalid_grant 400 Hindi kilala, expired, nagamit na, o ibinigay sa ibang app ang code o refresh token, o hindi tugma ang redirect_uri o code_verifier nito. Ibinabalik din ito pagkatapos i-deauthorize ng user ang app mo.
invalid_request 400 May kulang na required field, o hindi form-encoded ang body.
invalid_scope 400 Humingi ang refresh ng scope na wala sa orihinal na grant.
unsupported_grant_type 400 authorization_code at refresh_token lang ang suportado.
slow_down 429 Masyadong maraming failed na client authentication mula sa IP mo (30 kada minuto). Maghintay ng isang minuto.

Nakakakuha ng 401 ang API calls na may mali, expired o na-revoke na token; 403 (50001 Missing Access) naman ang token na walang kinakailangang scope. May karaniwang X-RateLimit-* headers ang mga response, binibilang kada user kada app.

Kapag natapos ang access

Puwedeng tumigil gumana ang token bago pa ito mag-expire. Nangyayari ito kapag:

  • na-click ng user ang Deauthorize sa ilalim ng Settings > Authorized Apps (sabay-sabay na titigil gumana ang lahat ng token na hawak mo para sa kanila, at buburahin ang linked-role entry mo para sa kanila)
  • na-disable ang account ng user
  • na-delete ang application mo
  • na-suspend ang developer account mo

Ituring ang 401 o invalid_grant na “naka-sign out” at ipadaan ulit ang user sa step 1.

Kumpletong halimbawa (Node.js + Express)

Sign-in na may state checking, ang code exchange, at pagbasa sa user. Node 18+ para sa built-in na fetch.

import express from 'express';
import crypto from 'node:crypto';

const CLIENT_ID = process.env.GAMEVOX_CLIENT_ID;
const CLIENT_SECRET = process.env.GAMEVOX_CLIENT_SECRET;
const REDIRECT_URI = 'https://yourapp.example.com/auth/gamevox';

// state must be tied to THIS browser, or someone can hand a victim a callback
// URL carrying the attacker's own code and sign them in as the attacker.
// A short-lived HttpOnly cookie does that without a session store.
const STATE_COOKIE = 'gv_oauth_state';
const readCookie = (req, name) =>
  (req.headers.cookie || '').split(';').map((c) => c.trim().split('='))
    .find(([k]) => k === name)?.[1] || '';

const app = express();

app.get('/login', (req, res) => {
  const state = crypto.randomBytes(16).toString('hex');
  res.cookie(STATE_COOKIE, state, {
    httpOnly: true, secure: true, sameSite: 'lax', maxAge: 10 * 60 * 1000, path: '/auth/gamevox',
  });
  const url = new URL('https://gamevox.com/oauth2/authorize/');
  url.search = new URLSearchParams({
    response_type: 'code',
    client_id: CLIENT_ID,
    scope: 'identify email',
    redirect_uri: REDIRECT_URI,
    state,
  }).toString();
  res.redirect(url.toString());
});

app.get('/auth/gamevox', async (req, res) => {
  const { code, state, error } = req.query;
  const expected = readCookie(req, STATE_COOKIE);
  res.clearCookie(STATE_COOKIE, { path: '/auth/gamevox' });
  if (!expected || typeof state !== 'string' || state !== expected) {
    return res.status(400).send('Login expired or started in another browser');
  }
  if (error) return res.redirect('/?login=cancelled');
  if (typeof code !== 'string') return res.status(400).send('Missing code');

  const tokenRes = await fetch('https://app-api.gamevox.com/api/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: 'Basic ' + Buffer.from(CLIENT_ID + ':' + CLIENT_SECRET).toString('base64'),
    },
    body: new URLSearchParams({ grant_type: 'authorization_code', code, redirect_uri: REDIRECT_URI }),
  });
  if (!tokenRes.ok) return res.status(502).send('GameVox login failed');
  const tokens = await tokenRes.json();

  const me = await fetch('https://app-api.gamevox.com/api/users/@me', {
    headers: { Authorization: 'Bearer ' + tokens.access_token },
  }).then((r) => r.json());

  // me.id is the stable GameVox user id: key your account record on it.
  // Store tokens.refresh_token server-side if you need access later.
  res.send('Signed in as ' + me.username);
});

app.listen(3000);

Mga pagkakaiba sa Discord

  • Authorization-code grant lang. Walang implicit grant (response_type=token) at walang client_credentials.
  • Walang public clients: kailangan ng client secret sa bawat token request, may PKCE man o wala.
  • Hindi pa available ang user installs (applications.commands na walang bot, integration_type=1).
  • Walang connections, guilds.join, guilds.members.read o rpc scopes.
  • Sa /users/@me/guilds, summary para sa pagpili ng server ang permissions, hindi buong kalkulasyon (tingnan sa itaas).

← Bumalik sa docs