Premium¶
TEBHOS has three paid products, all sold through Polar (see Billing):
- TEBHOS Pro — a personal subscription (monthly or yearly). Pro members show a blue badge and get Pro perks, including 10 free guild boosts in total.
- Guild boosts — raise a guild's boost level. Each boost lasts 30 days.
- Business Class (İş Sınıfı) — a per-guild subscription bought by the guild owner. The guild gets a yellow badge and level 2 boost perks, and its owner gets Pro perks.
The cosmetics shop is covered at the end of this page. Gifts covers gift codes.
Every route on this page requires a user session; bot tokens are rejected with 403 ACCESS_DENIED.
Premium types¶
| Value | Name | Description |
|---|---|---|
| 0 | Free | No premium (shown to users as "TEBHOS Başlangıç") |
| 1 | Monthly | Monthly TEBHOS Pro, 30 days per period |
| 2 | Yearly | Yearly TEBHOS Pro, 365 days per period |
| 3 | Lifetime | TEBHOS Pro with no end date |
Premium is active when the type is 3, or when the type is 1 or 2 and premiumUntil is in the future. The owner of a guild with an active Business Class subscription is reported as premium (type 1, Monthly) until that subscription ends, even without a Pro subscription.
Premium status object¶
Returned by Get my premium status and by Cancel premium. Field names use camelCase.
| Field | Type | Description |
|---|---|---|
| premiumType | integer | The premium type |
| premiumTypeName | string | Free, Monthly, Yearly or Lifetime |
| isPremium | boolean | Whether premium is currently active |
| premiumSince | ?ISO8601 timestamp | When premium started |
| premiumUntil | ?ISO8601 timestamp | When premium ends; null for lifetime or free |
| daysRemaining | ?integer | Days until premiumUntil |
| premiumDays | integer | Credited premium days (time elapsed plus the remaining active period), used to unlock badge tiers; 0 when not premium |
| premiumWillCancel | boolean | Whether premium is scheduled to end at premiumUntil instead of renewing |
Example¶
{
"premiumType": 1,
"premiumTypeName": "Monthly",
"isPremium": true,
"premiumSince": "2026-09-01T10:00:00Z",
"premiumUntil": "2026-10-01T10:00:00Z",
"daysRemaining": 8,
"premiumDays": 30,
"premiumWillCancel": false,
"has_billing_account": true
}
Get my premium status¶
GET /premium/me
Returns the caller's premium status object, plus:
| Field | Type | Description |
|---|---|---|
| has_billing_account | boolean | Whether the caller has a Polar subscription with a customer record, which enables the customer portal |
Get premium state¶
GET /premium/state
Returns the caller's premium state in a nested {actual, effective, billing, pricing} shape. Only a few fields carry TEBHOS data:
| Field | Description |
|---|---|
| actual.premium_type / effective.premium_type | 1 when premium is active, otherwise null |
| actual.premium_since, actual.premium_until | Same as premiumSince / premiumUntil above |
| actual.premium_will_cancel | Whether the subscription ends at premium_until |
| actual.premium_billing_cycle | monthly, yearly or null |
| actual.has_active_paid_premium | Whether premium is active |
Not supported on TEBHOS
The billing and pricing sections are always empty (null, [] or false), effective.is_premium is always true, effective.self_hosted is always true, and is_visionary, premium_lifetime_sequence and premium_grace_ends_at are always false/null. Use Get my premium status and List transactions instead.
Check users' badges¶
POST /premium/check
Resolves which of the given users show a premium (blue) or Business Class (yellow) badge, and their affiliation badges. Any authenticated user can call it.
JSON body¶
| Field | Type | Description |
|---|---|---|
| ids | array[snowflake] | The user IDs to check. Invalid IDs are ignored |
Response¶
| Field | Type | Description |
|---|---|---|
| premium_ids | array[snowflake] | Users with active TEBHOS Pro |
| business_ids | array[snowflake] | Users who own a guild with active Business Class. Clients show the yellow badge instead of the blue one for these users |
| affiliation_badges | array[object] | {user_id, guild_id, icon_hash, guild_name} for users whose primary Business Class affiliation should be shown next to their name |
Guild boosts¶
A guild's boost level comes from the number of boosts currently counting toward it:
| Level | Active boosts |
|---|---|
| 0 | 0-9 |
| 1 | 10-24 |
| 2 | 25 or more |
Level 2 is the highest level, and it is required for a guild to appear in Discovery. At most 25 boosts count toward a guild at the same time; additional boosts wait as pending and start their 30-day period when a slot frees up. Pending boosts still count for the booster's own badge tiers.
A guild with active Business Class has an effective level of at least 2.
TEBHOS Pro members have 10 free boosts in total (not per month). A boost that expires or is removed does not return a free boost. Boosts beyond the free allowance, and all boosts for non-Pro users, are paid through Polar at 49,99 TL (2,99 USD) each.
Get my boost status¶
GET /users/@me/boost-status
Returns the caller's boosting summary across all guilds (camelCase):
| Field | Type | Description |
|---|---|---|
| isBoosting | boolean | Whether the caller has any active or pending boost |
| boostingSince | ?ISO8601 timestamp | When the caller's oldest current boost was created |
| boostCount | integer | Number of the caller's active or pending boosts |
| boostDays | integer | Credited boost days used for badge tiers |
| boostSlots | null | Always null (there is no per-user limit) |
| boostSlotsUsed | integer | Same as boostCount |
| boostSlotsRemaining | null | Always null |
| isPremium | boolean | Whether the caller has TEBHOS Pro |
| boostUnitPriceMinor | integer | Price of one boost in kuruş (4999) |
| boostCurrency | string | TRY |
| boostUnitPriceUsdMinor | integer | Price of one boost in US cents (299) |
| freeBoostAllowance | integer | Total free boosts for this account (10 for Pro, otherwise 0) |
| freeBoostsUsed | integer | Free boosts already used |
| freeBoostRemaining | integer | Free boosts left |
Get guild boosts¶
GET /servers/{guild_id}/boost
Returns the boost state of a guild. Reading it also promotes pending boosts into free slots.
| Field | Type | Description |
|---|---|---|
| boostCount | integer | Total boosts on the guild (active and pending) |
| level | integer | The boost level from active boosts |
| effectiveLevel | integer | The level used for perks (at least 2 with Business Class) |
| isBoosting | boolean | Whether the caller boosts this guild |
| myBoostCount | integer | The caller's boosts on this guild (active and pending) |
| userBoost | ?object | {id, createdAt, expiresAt} of the caller's oldest active boost here |
| goal | integer | The guild's boost goal for the progress bar (default 25, display only) |
| barEnabled | boolean | Whether the guild shows the boost progress bar |
Boost guild¶
POST /servers/{guild_id}/boost
Boosts a guild. Free boosts are applied immediately; any paid remainder is charged in one Polar checkout.
JSON body¶
The body is optional.
| Field | Type | Description |
|---|---|---|
| count? | integer | Number of boosts to add (1-100, default 1; clamped) |
| currency? | string | try or usd, see checkout currency |
Response¶
When every requested boost was covered by free boosts, the route returns 201:
{
"id": "1501314428688998190",
"message": "...",
"free": true,
"applied": 1,
"priceMinor": 0,
"currency": "TRY",
"freeBoostRemaining": 9
}
When payment is needed, it returns 200 with a checkout URL. The paid boosts are applied after Polar confirms the payment; the browser returns to the guild's boost page.
{
"paymentRequired": true,
"url": "https://checkout.example.com/polar_c_1a2b3c",
"freeApplied": 3,
"paidCount": 7,
"priceMinor": 34993,
"unitPriceMinor": 4999,
"currency": "TRY",
"freeBoostRemaining": 0
}
| Status | Body | Condition |
|---|---|---|
| 201 | free result | All boosts were applied for free |
| 200 | payment result | Some or all boosts need payment |
| 400 | error response | Paid boosts are not configured on this instance (BAD_REQUEST) |
| 409 | error response | Another boost request by the same user is still in progress (CONFLICT); retry after a few seconds |
Applying boosts re-indexes the guild for Discovery and dispatches a Guild Update.
Remove my boosts¶
DELETE /servers/{guild_id}/boost
Removes all of the caller's boosts from the guild and returns {"message": "..."}. Free boosts used on them are not returned. The guild is re-indexed and a Guild Update is dispatched.
List boosters¶
GET /servers/{guild_id}/boost/boosters
Returns the guild's boosters, oldest first, grouped per user:
[
{
"profileId": "1501314428688998182",
"name": "example",
"imageUrl": "",
"boostCount": 3,
"boostedAt": "2026-09-01T10:00:00Z"
}
]
Business Class¶
Business Class is a subscription attached to one guild and bought by its owner through Create Business Class checkout. While it is active:
- the guild has the
BUSINESS_CLASSguild feature and shows a yellow badge, - the guild gets level 2 boost perks (its effective boost level is at least 2),
- the owner is treated as a TEBHOS Pro member,
- the owner can link up to 25 members to the guild with affiliations,
- anyone can join the guild through Join discovery guild.
Owner-only routes answer 404 NOT_FOUND to anyone who is not the guild owner, so they do not reveal whether the guild exists.
Business Class subscription object¶
| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The guild |
| active | boolean | Whether the subscription is currently live |
| until | ?ISO8601 timestamp | When the current period ends |
| will_cancel | boolean | Whether it ends at until instead of renewing |
| billing_cycle | ?string | monthly or yearly |
| discovery_opt_in | boolean | Whether the guild is listed in Business Class discovery |
Get my Business Class overview¶
GET /business/me
Lists every guild the caller owns with its Business Class state:
{
"guilds": [
{
"guild_id": "1489002177550843904",
"name": "Example guild",
"icon_hash": null,
"business": null,
"business_active": false
}
],
"has_live": false
}
business is a subscription object or null.
Get guild Business Class¶
GET /business/guilds/{guild_id}
Owner only. Returns {"business": <subscription object or null>, "business_active": <bool>}.
Set Business Class discovery listing¶
PUT /business/guilds/{guild_id}/discovery
Owner only. Body {"enabled": true} or {"enabled": false}. Returns {"discovery_opt_in": <bool>}. The subscription alone does not list the guild; this opt-in is required.
List Business Class guilds¶
GET /business/discovery
Returns the live Business Class guilds that opted in to discovery:
| Field | Type | Description |
|---|---|---|
| guilds[].guild_id | snowflake | The guild |
| guilds[].name | ?string | The guild name |
| guilds[].icon_hash | ?string | The guild icon hash |
| guilds[].banner_hash | ?string | The guild banner hash |
| guilds[].member_count | integer | The member count |
| guilds[].owner | ?object | {user_id, username, name, image_url} of the owner |
Business Class affiliations¶
An affiliation links a guild member to a Business Class guild; the member can then show the guild's logo next to their name. The owner sends a request, and the member accepts or declines.
| Route | Who | Description |
|---|---|---|
GET /business/guilds/{guild_id}/affiliations |
Owner | Lists affiliations as {affiliations: [{user_id, status, username, name, image_url, created_at}], limit} |
POST /business/guilds/{guild_id}/affiliations |
Owner | Sends a request. Body {"user_id": "..."} or {"username": "..."}. The target must be a member of the guild. Returns {ok, status} |
DELETE /business/guilds/{guild_id}/affiliations/{user_id} |
Owner | Removes an affiliation |
GET /business/affiliations/me |
Member | Lists the caller's affiliations as {affiliations: [{guild_id, status, is_primary, guild_name, guild_icon_hash}]} |
POST /business/affiliations/{guild_id}/respond |
Member | Body {"accept": true} accepts, false declines. Returns {ok, accepted} |
POST /business/affiliations/{guild_id}/primary |
Member | Makes an accepted affiliation the one shown next to the caller's name |
DELETE /business/affiliations/{guild_id} |
Member | Leaves an affiliation (204) |
Affiliation statuses are pending, accepted and inactive. A guild can hold at most 25 affiliations that are not inactive. Sending a request is limited to 30 per hour per user (business:affiliate bucket).
Shop¶
The shop sells profile cosmetics. Purchases go through a Polar checkout; an item is added to the inventory after payment.
Cosmetic slots¶
| Slot | Description |
|---|---|
| NAME_PLATE | Name plate shown behind the name in member lists |
| AVATAR_DECORATION | Decoration around the avatar |
| PROFILE_EFFECT | Animated effect on the profile |
| AVATAR_HAT | Hat on the avatar |
| APP_LOGO | App logo cosmetic |
List shop collections¶
GET /shop/collections
Returns {collections, items, bundles}. Items have id, slug, collection_id, name, description, item_type (a slot), price, premium_price, asset_data and purchasable; bundles have id, slug, collection_id, name, description, price, premium_price, item_ids and purchasable. purchasable is false when the item has no Polar product configured.
Get inventory¶
GET /shop/inventory
Returns {"entries": [{id, item_id, source, bundle_id, purchased_at}]} for the caller.
Get equipped cosmetics¶
GET /shop/equipped
Returns the caller's equipped item per slot as {name_plate, avatar_decoration, profile_effect, avatar_hat, app_logo} (each an item or null). POST /shop/equipped/bulk with {"profile_ids": [...]} returns the same for several users, keyed by user ID.
Purchase shop item¶
POST /shop/items/{item_id}/purchase
Opens a Polar checkout for one item and returns a redirect URL object.
| Field | Type | Description |
|---|---|---|
| currency? | string | try or usd |
| gift_recipient_id? | snowflake | Buy the item as a gift for this user; it is delivered to them after payment |
| gift_message? | string | A note for the gift recipient, truncated to 190 characters |
Returns 400 when the buyer (or the gift recipient) already owns the item, when the recipient is the caller, or when the item cannot be purchased; 404 when the item or recipient does not exist.
Purchase shop bundle¶
POST /shop/bundles/{bundle_id}/purchase
Same as Purchase shop item for a bundle.
Equip a cosmetic¶
PATCH /shop/equipped/{slot}
Body {"item_id": "<item uuid>"} equips an item in the slot; {"item_id": null} clears the slot. The item type must match the slot. The caller must own the item, except for Pro-only items, which require TEBHOS Pro (or a gifted copy). Returns the caller's equipped cosmetics.
Cosmetic gifts¶
GET /shop/cosmetic-gifts lists unclaimed cosmetic gifts sent to the caller as {"gifts": [{id, sender_id, item_type, item_id, message}]}. POST /shop/cosmetic-gifts/claim claims them and returns 204.