Incentives
Create recurring incentives and read their analytics
Recurring incentives are reward programs that evaluate user activity on a recurring schedule (epochs) and distribute rewards to participants. Each recurring incentive has one or more epochs; each epoch runs a query, produces a leaderboard, and either distributes rewards automatically or opens a claim window.
This page covers both creating and managing incentives and reading analytics for them.
Create & Manage
create_recurring_incentive
Create a recurring incentive on the active project.
Requires: authentication, active project
Prerequisite tool: generate_incentive_query — to obtain a validated sqlQuery for the incentive source.
A recurring incentive is three layers:
- Query —
sqlQueryfromgenerate_incentive_query(what activity is measured). - Type —
leaderboard,rebate,raffle, ordirect(how rewards are shaped — see Incentive Types). - Rewards — tokens or SOL, amounts, schedule, and optional per-participant cap.
Always call with confirmed: false first and present the preview to the user. The preview surfaces the 5%
protocol fee (added on top of totalFundAmount, so the creator pays totalFundAmount × 1.05) and the
7-day claim window so the user can approve the full cost before creation.
Core parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name |
description | string | No | Description |
type | "leaderboard" | "rebate" | "raffle" | "direct" | Yes | Reward distribution type |
emissionType | "TOKENS" | "SOL" | Yes | Type of reward emission |
totalFundAmount | number | Yes | Total reward pool per epoch. Ignored for raffle (derived from raffleBuckets sum) and direct (derived from allocations sum). |
startDate | string | Yes | ISO 8601 start date for the first epoch's evaluation |
confirmed | boolean | No | Set to true to execute. Omit to preview. |
Schedule
| Parameter | Type | Description |
|---|---|---|
evalDurationDays | number | Duration of each epoch in days (e.g. 1, 7, 30). |
interval | "DAILY" | "WEEKLY" | "MONTHLY" | Shorthand for evalDurationDays (1, 7, 30 respectively). |
maxIterations | number | Maximum epochs to run. Omit for unlimited. |
Provide either evalDurationDays or interval. evalDurationDays takes priority if both are given.
Token configuration
| Parameter | Type | Description |
|---|---|---|
tokenAddress | string | SPL token mint address (required if emissionType is "TOKENS") |
tokenDecimals | number | Token decimal places (required if emissionType is "TOKENS") |
Query & formula
| Parameter | Type | Description |
|---|---|---|
sqlQuery | string | SQL query from generate_incentive_query. Required for every type except direct (which auto-constructs from allocations). |
customEventId | string | Custom event ID — set when the incentive is based on a custom event. Mutually exclusive with instructionId. |
instructionId | string | IDL instruction ID — set when the incentive is based on an on-chain instruction. Mutually exclusive with customEventId. |
customFormula | string | Reward formula. See Formulas. |
maxPerParticipant | number | Maximum reward per user per epoch |
For leaderboards, always ask the user how they want rewards distributed (fixed rank prizes, tiered
ranges, equal splits, capped metric, etc.) and build customFormula from their intent. The fallback N
pays each user their raw metric value — rarely intended (e.g. would give a trader back their full trade
volume).
Type-specific parameters
Rebate:
| Parameter | Type | Description |
|---|---|---|
rebatePercentage | number | Rebate percentage (e.g. 5 for 5%). The formula VALUE * (rebatePercentage / 100) is constructed automatically. |
Raffle:
| Parameter | Type | Description |
|---|---|---|
raffleBuckets | array | Prize tiers: [{ amount: number, count: number }]. totalFundAmount is derived from the sum. |
raffleWeighting | "WEIGHTED_BY_METRIC" | "EQUAL_CHANCES" | Default: WEIGHTED_BY_METRIC — each user's metric value = ticket count. Use EQUAL_CHANCES for 1 ticket per qualifying user. |
For raffles, always ask the user how tickets should be distributed — WEIGHTED_BY_METRIC (more activity = more chances) or EQUAL_CHANCES (everyone gets equal odds).
Direct:
| Parameter | Type | Description |
|---|---|---|
allocations | array | string | Wallet allocations: array of { address, amount } or CSV string (one address,amount per line) |
direct describes how allocations are supplied (the user hands them in), not a payout shape. Internally
it is persisted as type: LEADERBOARD, distributionType: FORMULA, customFormula: "N" — each wallet gets the
amount you gave it. A customFormula can still be supplied to transform the allocation values (e.g.,
min(N, 500) to cap each payout).
list_recurring_incentives
List all recurring incentives on the active project, rendered as a markdown table with recurringOfferId, name, type, epoch cadence, and status.
Requires: authentication, active project
No parameters.
The returned recurringOfferId is needed by get_recurring_incentive, get_epoch_aggregate_stats, and get_epoch_leaderboard.
get_recurring_incentive
Get the full configuration of one recurring incentive — distribution settings, schedule, query info, and the list of epochs (each epoch's epochConfigId, status, and timing).
Requires: authentication, active project
Prerequisite tool: list_recurring_incentives — to obtain recurringOfferId.
| Parameter | Type | Required | Description |
|---|---|---|---|
recurringOfferId | string | Yes | The recurring incentive ID |
Use this to find epochConfigId values for get_epoch_leaderboard.
Analytics
get_epoch_aggregate_stats
Aggregate stats per epoch for one recurring incentive — total participants, total distributed, claim rate, and status, one row per epoch. Renders as a markdown table.
Requires: authentication, active project
Prerequisite tool: list_recurring_incentives — to obtain recurringOfferId.
| Parameter | Type | Required | Description |
|---|---|---|---|
recurringOfferId | string | Yes | The recurring incentive ID |
This tool is not per-wallet. Use get_epoch_leaderboard for per-wallet rankings, allocations, or payout
status.
get_epoch_leaderboard
Per-wallet entries for one epoch of a recurring incentive — leaderboard standings, recipient allocations with payout status, or a full CSV export, switched by mode.
Requires: authentication, active project
Prerequisite tools: list_recurring_incentives → recurringOfferId; get_recurring_incentive → epochConfigId (omit for the latest epoch).
| Parameter | Type | Required | Description |
|---|---|---|---|
recurringOfferId | string | Yes | The recurring incentive ID |
mode | "preview" | "recipients" | "download" | No | What to fetch (default: "preview") |
epochConfigId | string | No | Target a specific epoch. Behavior when omitted varies by mode (see below). |
limit | number | No | Max rows (default: 50). Applies to preview and recipients only. |
offset | number | No | Pagination offset (default: 0). Applies to preview and recipients only. |
Modes:
preview(default) — top-N ranked wallets with their metric values.epochConfigIdomitted → uses the latest evaluation results.recipients— per-wallet allocations and payout status (DISTRIBUTED,PENDING,FAILED).epochConfigIdomitted → auto-picks the latest epoch inEVALUATING,CLAIMING, orCOMPLETEDstatus.download— signed CSV URL (5-minute expiry) for the full export.epochConfigIdomitted → uses the latest epoch's query.
Do not use preview_incentive_query for live incentive results — that tool is creation-time only. For
live results, always use get_epoch_leaderboard.