Skip to main content

Sign in with VRChat Legends

Register an application in Developer tools. Register the exact callback URL your application uses.

  1. Send the user to GET /api/oauth2/authorize with client_id, redirect_uri, response_type=code, scope, and a random state bound to their session.
  2. Verify returned state before accepting the callback.
  3. Exchange the code at POST /api/oauth2/token using grant_type=authorization_code, code, redirect_uri, and client_id. Confidential clients authenticate with their secret. Public clients use PKCE S256 and send the original code_verifier.
  4. Request GET /api/oauth2/userinfo with the returned bearer token.

The identify scope covers identity and permitted public profile data. Request email only when your application needs it and the user consents. Never put client secrets in browser JavaScript.

Use POST /api/oauth2/revoke to revoke a token. Treat authorization codes as single-use credentials and handle expiry by restarting authorization.

Request fields​

EndpointFields
GET /api/oauth2/authorizeclient_id, exact redirect_uri, response_type=code, space-separated scope, and state
PKCE authorizationAlso send code_challenge and code_challenge_method=S256
POST /api/oauth2/tokengrant_type=authorization_code, code, redirect_uri, client_id, plus client authentication or code_verifier
GET /api/oauth2/userinfoAuthorization: Bearer ACCESS_TOKEN
POST /api/oauth2/revoketoken and application authentication

The token endpoint accepts form or JSON bodies and supports HTTP Basic client authentication. OAuth access tokens (vrclat_…) are for the OAuth endpoints; they are not interchangeable with personal API keys (vrcl_…) used for profile editing.

Check HTTP status and the returned error before storing credentials. A user may cancel consent. A callback without the expected state, with an error, or with a reused/expired code must not create a signed-in application session. Read expires_in from the token response rather than hardcoding a lifetime.