Rewards
Overview
The rewards module manages channel rewards (e.g., Twitch Channel Points) with full CRUD operations. Each reward is scoped to an account and platform, with an optional link to the platform's native reward ID. Rewards carry a configurable action JSONB field that defines what happens when the reward is redeemed.
Architecture
Dashboard UI
|
v
Next.js API Proxy (/api/rewards)
|
v
GraphQL (RewardQuery / RewardMutation)
|
v
db::rewards (PostgreSQL)
Rewards are stored in the channel_rewards table and can be synced with external platform reward systems via the platform_reward_id field. The action JSONB field allows flexible behavior configuration without schema changes.
API
GraphQL Queries
| Query | Args | Returns | Permission |
|---|---|---|---|
rewards | -- | [Reward] | rewards:read |
reward | id: UUID | Reward? | rewards:read |
rewardsreturns all rewards for the active account, ordered bycreated_at ASC.rewardreturns a single reward by ID, filtered by account ownership.
GraphQL Mutations
| Mutation | Args | Returns | Permission |
|---|---|---|---|
createReward | input: CreateRewardInput | Reward | rewards:create |
updateReward | input: UpdateRewardInput | Reward | rewards:edit |
deleteReward | id: UUID | DeleteRewardResult | rewards:delete |
All mutations verify account ownership before proceeding.
GraphQL Types
type Reward {
id: UUID!
accountId: UUID!
platform: String!
platformRewardId: String
title: String!
cost: Int
enabled: Boolean!
action: JSON!
createdAt: String!
updatedAt: String!
}
input CreateRewardInput {
platform: String!
platformRewardId: String
title: String!
cost: Int
action: JSON
}
input UpdateRewardInput {
id: UUID!
title: String
cost: Int
enabled: Boolean
action: JSON
}
type DeleteRewardResult {
success: Boolean!
}
REST Endpoints
Rewards are currently exposed only via GraphQL. There is no dedicated /v1/rewards REST resource; to CRUD rewards from an external script, use GraphQL directly.
Action JSONB
The action field is a flexible JSONB object that defines reward behavior. It defaults to {} if not provided during creation. The structure is application-defined and can vary per use case (e.g., trigger an overlay alert, play a sound, enable a chat mode).
Permissions
| Permission | Description |
|---|---|
rewards:read | List and view rewards |
rewards:create | Create new rewards |
rewards:edit | Update existing rewards |
rewards:delete | Delete rewards |
Included in: Owner, Administrator roles. Moderator and Viewer roles have rewards:read only.
Database
Table: channel_rewards
| Column | Type | Description |
|---|---|---|
id | UUID (PK) | Reward ID |
account_id | UUID (FK) | Owning account |
platform | TEXT | Platform identifier (e.g., twitch) |
platform_reward_id | TEXT | External platform reward ID (for sync) |
title | TEXT | Reward display title |
cost | INT | Point cost (nullable) |
enabled | BOOLEAN | Whether the reward is active |
action | JSONB | Configurable reward action payload |
created_at | TIMESTAMPTZ | Creation timestamp |
updated_at | TIMESTAMPTZ | Last update timestamp |
DB Functions
| Function | Description |
|---|---|
list_rewards | List all rewards for an account, ordered by created_at ASC |
get_reward | Get a single reward by ID |
create_reward | Insert a new reward |
update_reward | Partial update using COALESCE for optional fields |
delete_reward | Delete by ID, returns whether a row was deleted |
Key Files
| File | Purpose |
|---|---|
apps/api/src/graphql/rewards.rs | GraphQL queries, mutations, input/output types |
apps/api/src/db/rewards.rs | Database CRUD operations |
crates/lo-auth/src/rbac.rs | Permission constants (rewards:read/create/edit/delete) |