Connect Whitoo to your own software.

From sign-in to server management, from posting messages to publishing community content — do what Whitoo does, from your own site or bot. The first request below needs no key; copy it and run it.

Quickstart

Four steps. The first needs no key; the rest run with the user's consent.

Read public data

The server directory, categories and counts are public. No signup needed.

curl https://whitoo.com/api/v1/public/stats

Create your application

Use My applications below: pick a name, a callback URL and the permissions you need. You get a client_id and a client_secret shown once.

Send the user to the consent screen

The user sees each permission separately. code_challenge (PKCE) is required for clients that cannot keep a secret.

https://whitoo.com/oauth/whitoo/start
  ?client_id=SENIN_CLIENT_ID
  &redirect_uri=https://site.com/callback
  &state=rastgele_deger
  &code_challenge=BASE64URL(SHA256(verifier))
  &code_challenge_method=S256

After consent the user returns with ?token=...&state=.... That code lives 60 seconds and is single-use.

Exchange the code and call

curl -X POST https://whitoo.com/oauth/whitoo/token \
  -d grant_type=authorization_code \
  -d client_id=... -d client_secret=... \
  -d code=... -d code_verifier=...

# then, with the access_token
curl https://whitoo.com/api/v1/users/@me \
  -H "Authorization: Bearer wat_..."

Access tokens last 1 hour, refresh tokens 30 days. Refresh tokens rotate on every use; reusing an old one is treated as theft and drops every token on that connection.

Access models

Three ways in. Which one you pick decides what you can reach.

No key /api/v1/public/*
Public data: server directory, categories, counts. Hidden servers never appear here.
On behalf of a user OAuth 2.0 + PKCE
The user consents and your app acts within their own permissions. They can revoke at any time.
Bot https://whitoo.com/api/bot/v1
A bot installed into a server. It works only in that server, with the permissions granted to it.

What you can build

Each row is a real scenario and the endpoint behind it.

A sign-in button
Users sign in with Whitoo. No passwords to store, no email verification to build. GEThttps://whitoo.com/oauth/whitoo/start
Their communities
List the servers they belong to and personalise your site around them. GET/api/v1/users/@me/servers
Manage channels
Open channels in bulk at season start, close them when an event ends. POST/api/v1/servers/{id}/channels
Grant and remove roles
Tie your membership tiers to Whitoo roles. PUT/api/v1/servers/{id}/members/{uid}/roles/{rid}
Post to a channel
Announce events from your system: an order arrived, a match started. POST/api/v1/channels/{cid}/messages
Send files and media
Upload reports, screenshots or audio straight to a channel. The type is verified from content. POST/api/v1/channels/{cid}/media
Your own moderation
Carry a violation from your system into Whitoo — never beyond the user's own permissions. POST/api/v1/servers/{id}/members/{uid}/mute
Who is in voice
A "12 people in voice right now" widget. Audio is never accessible — participants only. GET/api/v1/channels/{cid}/voice/members
Events and giveaways READ
Show the current list; send people to Whitoo to take part. Entry is not available via API. GET/api/v1/events · /giveaways · /tournaments
A community box
No key needed: server name, member count, online count and a join button. GET/api/v1/public/servers

How permission works

The API does not create a second permission world. Every management call passes two gates: the app's scope and the user's role permission in that server. Holding a scope is not enough — where the user cannot act, neither can the app.

# scope granted, role permission missing
HTTP/1.1 403 Forbidden
{
  "error": "missing_permission",
  "detail": { "required": "can_delete_channel", "server": 54 }
}

Endpoint index

Right column: the required scope and, for management calls, the required role permission.

Identity the user's own data

GET/api/v1/users/@meidentity
GET/api/v1/users/@me/emailemail
GET/api/v1/users/@me/serversservers.read
GET/api/v1/users/@me/programsprograms.read

Servers, channels, roles, members scope + role permission

GET/api/v1/servers/{id}servers.read
GET/api/v1/servers/{id}/channelschannels.read
POST/api/v1/servers/{id}/channelschannels.manage + can_create_channel
DEL/api/v1/servers/{id}/channels/{cid}channels.manage + can_delete_channel
GET/api/v1/servers/{id}/rolesroles.read
GET/api/v1/servers/{id}/membersmembers.read
POST/api/v1/servers/{id}/members/{uid}/{mute|kick|ban}members.moderate + can_mute/kick/ban_members
PUT/api/v1/servers/{id}/members/{uid}/roles/{rid}members.moderate + can_manage_roles
DEL/api/v1/servers/{id}/members/{uid}/roles/{rid}members.moderate + can_manage_roles
GET/api/v1/servers/{id}/invitesinvites.write + can_create_invite
POST/api/v1/servers/{id}/invitesinvites.write + can_create_invite

Messages, media, voice

GET/api/v1/channels/{cid}/messagesmessages.read
POST/api/v1/channels/{cid}/messagesmessages.write + can_send_messages
DEL/api/v1/channels/{cid}/messages/{mid}messages.manage + can_delete_message
POST/api/v1/channels/{cid}/mediamedia.write + can_attach_files
GET/api/v1/channels/{cid}/voice/membersvoice.read

Community content read only

GET/api/v1/eventscommunity.read
GET/api/v1/giveawayscommunity.read
GET/api/v1/tournamentscommunity.read
GET/api/v1/livecommunity.read
GET/api/v1/gamescommunity.read
GET/api/v1/users/{id}members.read

Events, giveaways, tournaments and games have no entry or creation endpoints. Private messages, passwords, two-factor data and payment details are never shared under any scope. A section switched off in the admin panel is off in the API too — it returns 404 feature_disabled.

No key needed try them right now

GET/api/v1/public/servers
GET/api/v1/public/servers/{slug}
GET/api/v1/public/categories
GET/api/v1/public/stats

Limits and errors

Limits are per minute, per application. Every response carries X-RateLimit-* headers.

Read300 / min
Listing and viewing calls.
Write60 / min
Messages, channels, roles, moderation, invites.
Media10 / min
File upload. Up to 50 MB; type verified from content.
# the error shape is always the same
{ "error": "...", "message": "...", "detail": { } }

401 invalid_token       missing, invalid or expired
403 missing_scope       the app never requested it
403 missing_permission  the user lacks the role permission
404 feature_disabled    section switched off in admin
422 validation_failed   missing or malformed field
429 rate_limited        see the Retry-After header

My applications