API Reference

Betterino API

Betterino is a modern fork of Chatterino — a Twitch chat client redesigned with a refined aesthetic and new features. This API powers badge management, user cosmetics, and authentication via Twitch OAuth.

Base URL https://api.ddrx.at/v1

User IDs

Most endpoints accept Internal ID, Twitch ID, or Betterino ID. Example: 3, 784897223, BT433914

Content Type

All request bodies must be sent as application/json. All responses are returned as JSON.

Authentication

Session Tokens

Betterino uses session tokens obtained via Twitch OAuth. Authenticated requests must include the token in the request header.

Required Header
X-Betterino-Token: bt_session_xxxxxxxxx
Basics

Response Format

All responses follow a consistent envelope structure.

Success
{
  "success": true,
  "data": {}
}
Error
{
  "success": false,
  "error": "Message"
}
System

Badge System

Badges are types (Betterino+, specials, …). Variants are the actual collectible designs, monthly or independent. Each variant has its own Tomoe images for levels 0–5. Owning Tomoe 3 unlocks T0–T3. On /badges the user picks a variant, previews any Tomoe, and can save any already unlocked level. Chat clients always receive the finished url for that displayed Tomoe.

Tomoe Levels

tomoe_level is owned progress (0–5). display_tomoe_level is the art shown in chat and may be any unlocked stage. Locked stages can be previewed on /badges but not saved.

Collector Tiers

Unlock collector badges by maxing variants (Tomoe 4+). Usual tiers: 1, 3, 5, 10, 15. Frames unlock from awakened badges. Manage art in Admin → Collector — do not create Collector as a badge series, and do not grant it.

Public API

Public Endpoints

No authentication required. Used primarily by chat clients to fetch badge data.

GET /badges/all All users + selected badges 🌐 Public

Returns all users and their currently selected visible badge. Used by chat clients to display badges in real-time. Always use selected_badge.url — it already points to the displayed Tomoe artwork, not necessarily the highest owned level.

Example Response
{
  "success": true,
  "count": 1,
  "updated_at": "2026-05-15T06:00:00Z",
  "users": {
    "784897223": {
      "betterino_id": "BT433914",
      "twitch_login": "deidaraxx",
      "selected_badge": {
        "selected_type": "user_badge",
        "id": 2,
        "user_badge_id": 2,
        "tomoe_level": 3,
        "display_tomoe_level": 2,
        "name": "Better Badge White Pearl",
        "url": "https://cdn.ddrx.at/badges/better-plus/BetterinoT2.webp"
      }
    }
  }
}
GET /badges/catalog Full badge catalog 🌐 Public

Returns the public catalog: badge types, variants, Tomoe images per variant, collector tiers, and collector frames. Each variant includes tomoe_levels and a resolved url for Tomoe 0.

GET /user/{id} Full user cosmetic data 🌐 Public

Returns full public cosmetic data for a user. Accepts Internal ID, Twitch ID, or Betterino ID. Owned badges and selected_badge always include the resolved image as url for the current Tomoe level. id is the user_badge_id used by /users/badges/select.

Example Request
GET /user/784897223
Example Response
{
  "success": true,
  "data": {
    "user": {
      "betterino_id": "BT433914",
      "display_name": "Deidaraxx",
      "roles": ["owner", "admin"],
      "subscribed": true
    },
    "selected_badge": {},
    "badges": [],
    "collection_badge": {},
    "awakening_progress": {}
  }
}
Auth API

Authentication

Endpoints for authenticating via Twitch and managing sessions.

POST /auth/twitch Authenticate via Twitch 🌐 Public

Authenticates a Twitch user using a Twitch access token. Returns a Betterino session token.

Request Body
{
  "access_token": "TWITCH_ACCESS_TOKEN"
}
Response
{
  "success": true,
  "auth": {
    "session_token": "bt_session_xxxxx",
    "expires_at": "2026-06-01 00:00:00",
    "user": {}
  }
}
GET /auth/me Get authenticated user 🔒 Auth required

Returns the currently authenticated user's profile based on the session token.

Response
{
  "success": true,
  "user": {
    "id": 3,
    "betterino_id": "BT433914",
    "roles": ["owner", "admin"]
  }
}
POST /auth/logout Invalidate session token 🔒 Auth required

Invalidates the current session token. No request body required.

User API

User Actions

Authenticated endpoints for managing your own badges and cosmetics.

POST /users/badges/select Select a visible badge 🔒 Auth required

Selects which badge is displayed. For a normal badge, send the user_badge_id as id and the unlocked Tomoe you want to show as tomoe_level. You may also send frame_id to overlay an unlocked collector frame on a normal badge. You may pick any Tomoe from 0 up to the owned upgrade level. Chat clients then receive that artwork in selected_badge.url and the overlay in selected_badge.frame.url.

Select Normal Badge + Tomoe + Frame
{
  "selected_type": "user_badge",
  "id": 2,
  "tomoe_level": 2,
  "frame_id": 1
}
Select Collector Badge With Frame
{
  "selected_type": "collector_badge",
  "id": 3,
  "frame_id": 1
}
Remove Visible Badge
{
  "selected_type": "none"
}
POST /users/badges/unselect Clear badge selection 🔒 Auth required

Alternative endpoint to clear the currently selected badge. No request body needed.

POST /users/badges/upgrade Upgrade badge Tomoe level 🔒 Auth required

Upgrades a badge to the specified Tomoe level. Target level must be higher than current level.

Request Body
{
  "user_badge_id": 2,
  "target_level": 4
}
Response
{
  "success": true,
  "upgrade": {
    "new_level": 4,
    "collection_badge": {}
  }
}
POST /users/badges/awaken Awaken a badge (Tomoe 5) 🔒 Auth required

Consumes an awakening unlock and awakens a badge to the hidden Tomoe level 5. Awakened badges count toward collector frames and are excluded from further awakening progress.

Request Body
{
  "user_badge_id": 2
}
Special Badges

Event redemptions

Public list of currently live specials, plus authenticated redeem endpoints. Codes are never returned by the public list — only requires_code.

GET /special-badges See available special badges 🌐 Public

Returns specials that are live right now. If a session token is sent, each item also includes owned, claimed and locked. Tomoe upgrades are locked until the user owns that variant.

Response
{
  "success": true,
  "special_badges": [{
    "id": 1,
    "name": "Christmas 2026",
    "requires_code": false,
    "tomoe_level": 0,
    "locked": false
  }]
}
POST /special-badges/redeem Redeem a special badge 🔒 Auth required

Redeems one live special by id. code may be null when the offer does not require one, or a value such as BETTERINO50.

Request Body
{
  "id": 1,
  "code": null
}
POST /special-badges/redeem-code Redeem a code 🔒 Auth required

Looks up every live special with this code and grants each one. Several Tomoe rows can share a code; they are applied one by one. Tomoe upgrades stay locked until the variant is owned.

Request Body
{
  "code": "BETTERINO50"
}
Admin API

Admin Endpoints

Requires an admin or owner session token. These endpoints allow full management of users, badges, and roles.

GET /admin/users List all users 🔒 Admin

Returns a list of all registered users.

GET /admin/users/{id} Detailed user info 🔒 Admin

Returns detailed user information including inventory, roles, collector progress, awakening progress, and selected badge.

POST /admin/badges/create Create a badge 🔒 Admin
Request Body
{
  "slug": "better-plus",
  "name": "Better Badge",
  "description": "Main Betterino+ badge",
  "type": "better_plus",
  "rarity": "subscription",
  "active": 1
}
POST /admin/badge-variants/create Create a badge variant 🔒 Admin

Creates a variant under an existing badge type. Send badge_id or badge_slug, or create a new type inline with new_badge. slug is optional and generated from name. Images are optional here — Tomoe art is managed separately. If base_image_url is sent, it becomes Tomoe 0.

Quick monthly variant
{
  "badge_id": 1,
  "name": "März 2026"
}
Create new badge type + variant
{
  "new_badge": {
    "slug": "special-event",
    "name": "Special Event",
    "type": "special"
  },
  "name": "Anniversary"
}
Full request (legacy fields still work)
{
  "badge_slug": "better-plus",
  "slug": "bb-month1",
  "name": "Better Badge Month 1",
  "unlock_month": 1,
  "base_image_url": "https://cdn.ddrx.at/badges/better-plus/bb-month1-t0.webp",
  "animated_image_url": null,
  "sort_order": 1,
  "active": 1
}
POST /admin/badge-tomoe/upsert Add or update a Tomoe image 🔒 Admin

Attaches a unique image to one Tomoe level of an existing variant. Select the variant with variant_id or variant_slug. If that level already exists, it is overwritten. Tomoe 0 also updates the variant's fallback base_image_url.

Request Body
{
  "variant_id": 1,
  "tomoe_level": 1,
  "name": "White Pearl Tomoe 1",
  "image_url": "https://cdn.ddrx.at/badges/better-plus/BetterinoT1.webp",
  "animated_image_url": null
}
POST /admin/badge-tomoe/delete Remove a Tomoe image 🔒 Admin

Deletes one Tomoe row. Send id, or variant_id + tomoe_level.

Request Body
{
  "id": 12
}
GET /admin/badge-options Dropdown data for admin UI 🔒 Admin

Returns existing badge types and variants so the admin UI can pick from lists instead of typing slugs.

GET /admin/collector-options List collector tiers and frames 🔒 Admin

Collector is a progress track, not a badge series. Returns all collector badge tiers and frames for the admin UI, including inactive rows.

POST /admin/collector-tiers/upsert Add or update a collector badge 🔒 Admin

Creates or overwrites one collector look. min_count is how many maxed badges (Tomoe 4+) unlock it. Usual values: 1, 3, 5, 10, 15. Sending the same min_count again overwrites that tier. Users are never granted these — they unlock automatically.

Request Body
{
  "min_count": 1,
  "name": "Collector I",
  "image_url": "https://cdn.ddrx.at/badges/collector/i.webp",
  "animated_image_url": null,
  "active": 1
}
POST /admin/collector-tiers/delete Delete a collector badge 🔒 Admin
Request Body
{
  "id": 1
}
POST /admin/collector-frames/upsert Add or update a collector frame 🔒 Admin

Creates or overwrites one overlay frame. min_awakened_count is how many awakened badges unlock it. Same number overwrites.

Request Body
{
  "min_awakened_count": 1,
  "name": "Frame I",
  "image_url": "https://cdn.ddrx.at/badges/frames/i.webp"
}
POST /admin/collector-frames/delete Delete a collector frame 🔒 Admin
Request Body
{
  "id": 1
}
POST /admin/users/grant-badge Grant badge to user 🔒 Admin
Request Body
{
  "user": "784897223",
  "variant_slug": "bb-month1",
  "source": "admin"
}
POST /admin/users/grant-tomoe Grant Tomoe progress 🔒 Admin

Grants at least this Tomoe level. If the user does not own the variant, it is granted first. Does not downgrade a higher owned level.

{
  "user": "784897223",
  "variant_slug": "bb-month1",
  "tomoe_level": 1
}
POST /admin/users/grant-collector Grant a collector look 🔒 Admin

Unlocks this collector tier for the user, including every lower min_count look.

{
  "user": "784897223",
  "collection_tier_id": 3
}
POST /admin/users/grant-frame Grant a collector frame 🔒 Admin

Unlocks this frame. It can then be selected on normal badges and collector badges.

{
  "user": "784897223",
  "frame_id": 1
}
GET /admin/special-redemptions List special redemptions 🔒 Admin

Admin list including codes and schedule fields. Each row also has live for the current Europe/Vienna window.

POST /admin/special-redemptions/upsert Create or update a special redemption 🔒 Admin

schedule_type: unlimited, yearly (repeating month/day window), or once (start_at / end_at). Reuse the same code on extra rows to attach several rewards to one redeem.

{
  "badge_variant_id": 4,
  "tomoe_level": 0,
  "requires_code": true,
  "code": "BETTERINO50",
  "schedule_type": "yearly",
  "start_month": 12,
  "start_day": 20,
  "end_month": 1,
  "end_day": 5
}
POST /admin/special-redemptions/delete Delete a special redemption 🔒 Admin

Removes the offer and its claim rows.

{
  "id": 1
}
POST /admin/users/remove-badge Remove user badge 🔒 Admin
Request Body
{
  "user_badge_id": 2
}
POST /admin/users/set-tomoe Set Tomoe level directly 🔒 Admin
Request Body
{
  "user_badge_id": 2,
  "tomoe_level": 5,
  "awakened": true
}
POST /admin/users/set-roles Set user roles 🔒 Admin

Sets user roles. Owners can manage admins and owners. Admins cannot manage admins or owners. Available roles: owner, admin, moderator, vip, founder, user

Request Body
{
  "user": "784897223",
  "roles": ["admin", "vip"]
}