Authentication

Every call your app makes is authenticated with an application secret, sent as a Bearer token.

Application secrets

Create secrets on your app's page at thexive.com/developers/console. A secret looks like xive_sa_… and is shown once, when you create it. Xive stores only a hash, so a lost secret cannot be shown again. Create a new one and revoke the old.

  • Send it on every request: Authorization: Bearer xive_sa_…
  • Several secrets can be active at the same time, so you can rotate without downtime. Create the new secret, deploy it, then revoke the old one.
  • A revoked secret stops working immediately.
  • Keep secrets on your server. Never put one in a browser page, a mobile app, an OBS browser source or anything else you ship to users. Anyone holding the secret can act as your app on every channel that added it.

Up to 5 secrets can be live per app. A hub bot secret (xive_as_…) does not work here — Hubs are a separate product. If your app is suspended, every secret stops working until it is reinstated.

Client types

You pick a client type when you create an app, and it can’t be changed afterwards.

  • Confidential: your app runs on a server you control and can keep a secret, like a chat bot or a web app. Confidential apps are issued secrets and can call every endpoint in these docs. If you’re unsure, pick this.
  • Public: your app can’t keep a secret, like a mobile, desktop or browser app or a game plugin. Public apps are never issued a secret. They get tokens through OAuth with PKCE instead.

Base URL

All endpoints in these docs are relative to:

https://api.thexive.com

Requests and responses are JSON. Send Content-Type: application/json with a body.

Verify your secret

GET /api/apps/@me returns the app the secret belongs to.

curl https://api.thexive.com/api/apps/@me \
  -H "Authorization: Bearer $XIVE_APP_SECRET"
{
  "success": true,
  "application": {
    "id": "9b1f3c52-6a0e-4d7b-8f4e-2c1d5a7e9b30",
    "client_id": "4f6c2a9e0d1b47c3a8e5f7b2c9d0e1a3",
    "name": "ModHelper",
    "icon_url": "https://media.xivecdn.com/…/icon.png"
  }
}

application.id is your application id; you will see it in the gateway channel name (app:<id>) and as the author of your bot's chat messages (app:<id>). client_id is the public id used in the "Add to channel" link.

A missing, wrong or revoked secret gets 401 with {"success": false, "error": "Invalid application credential"}.

OAuth: signing users in

OAuth lets someone sign in to your app with their Xive account (“Sign in with Xive”), and lets your app act on their own channel with the permissions they approve, without being added to it first. It follows Twitch's authentication: the same flows, endpoints and response shapes.

Tokens are streaming-only. They work on the bot API and nothing else. No token can post, comment, send messages, change a profile or touch money, whatever it asks for.

TokenStarts withLastsGet it with
User access tokenxive_ut_4 hoursAuthorization code (+ refresh)
Refresh tokenxive_rt_30 days (public clients) / 90 days (confidential), renewed on each refreshComes with a user token
App access tokenxive_at_30 daysClient credentials (confidential clients)

Send any token as Authorization: Bearer …, exactly like a secret.

1. Send the user to authorize

https://thexive.com/oauth2/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.example/auth/callback
  &response_type=code
  &scope=chat:read+user:read:email
  &state=RANDOM_VALUE
  &code_challenge=PKCE_CHALLENGE
  &code_challenge_method=S256
  • redirect_uri must exactly match one of your app's registered OAuth redirect URLs.
  • scope is optional. Without one, you get identity only (id, username, display name, avatar). Add user:read:email for their email, and any channel scope to act on their own channel.
  • state: a random value you check on the way back.
  • PKCE (code_challenge = base64url(SHA-256(verifier)), method S256) is required for public clients and recommended for everyone.

The user signs in if needed, sees your app (with a ✓ if it's verified) and what it asks for, and chooses. You get back ?code=…&scope=…&state=…, or ?error=access_denied&state=… if they cancel.

2. Exchange the code

curl -X POST https://api.thexive.com/api/oauth2/token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=xive_sa_… \
  -d code=CODE \
  -d grant_type=authorization_code \
  -d redirect_uri=https://yourapp.example/auth/callback \
  -d code_verifier=PKCE_VERIFIER
{
  "access_token": "xive_ut_…",
  "refresh_token": "xive_rt_…",
  "expires_in": 14400,
  "scope": ["chat:read", "user:read:email"],
  "token_type": "bearer"
}

A public client sends code_verifier and no secret. A confidential client sends client_secret (one of its xive_sa_ secrets); with PKCE it sends both. Codes work once and expire after 10 minutes.

3. Who signed in?

GET /api/apps/users with the user token and no parameters returns that user, with email if you have user:read:email. Use id as their stable identifier; usernames can change.

Refreshing

curl -X POST https://api.thexive.com/api/oauth2/token \
  -d grant_type=refresh_token \
  -d refresh_token=xive_rt_… \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=xive_sa_…     # confidential clients only

You get a new access and refresh token; the old pair stops working at once. Store the new refresh token every time.

Validating

Check a token the way Twitch does, and do it when your app starts and then hourly:

curl https://api.thexive.com/api/oauth2/validate -H "Authorization: OAuth xive_ut_…"
{ "client_id": "…", "login": "pixelpanda", "scopes": ["chat:read"], "user_id": "1f9a3b6c-…", "expires_in": 13820 }

401 means the token expired or was revoked: the user disconnected your app, or it was suspended. Refresh it, or send the user through sign-in again.

Revoking

curl -X POST https://api.thexive.com/api/oauth2/revoke -d client_id=YOUR_CLIENT_ID -d token=xive_ut_…

Revoke tokens when a user signs out of your app. Users can also disconnect your app from their Xive account at any time.

App access tokens

A confidential client can swap its secret for a 30-day app token, so the secret itself can stay in a vault:

curl -X POST https://api.thexive.com/api/oauth2/token \
  -d client_id=YOUR_CLIENT_ID -d client_secret=xive_sa_… -d grant_type=client_credentials

An app token can do what the secret can: everything on channels that added your app, plus the public lookups.

Errors

The OAuth endpoints answer errors in Twitch's shape: {"status": 400, "message": "Invalid authorization code"}. A wrong secret is 403; an unknown client, a reused or expired code, a wrong redirect_uri or a bad code_verifier is 400.