Skip to main content
Using an AI coding assistant? Connect Cursor, Claude, or Copilot to Snag Docs for context-aware help. Learn how.

Overview

Loyalty rules define how users earn points, multipliers, or badges in your loyalty program. Each rule type has specific requirements for parameters, metadata, and configuration. This guide covers all available rule types and their required fields.

Common Parameters

All loyalty rules share these common parameters:
organizationId
string
required
The organization ID that owns this rule.
websiteId
string
required
The website ID where this rule will be applied.
name
string
required
The name of the loyalty rule (max 255 characters).
description
string
Optional description of the rule.
type
LoyaltyRuleType
required
The type of loyalty rule. See available types below.
frequency
LoyaltyRuleFrequency
required
How often eligibility is checked. Options: once, daily, weekly, monthly, immediately.
interval
LoyaltyRuleInterval
How often users can earn rewards. Options: once, daily, weekly, monthly, unlimited, custom.
startTime
ISO8601 string
required
When the rule becomes active (ISO 8601 format).
endTime
ISO8601 string
Optional end time for the rule (ISO 8601 format).
rewardType
LoyaltyRuleRewardType
required
Type of reward: points, multiplier, or badge.
loyaltyCurrencyId
string
required
The ID of the loyalty currency (points) to reward.
network
NetworkType
required
The blockchain network. Options: mainnet, goerli, polygon, arbitrum, etc.

Reward Configuration

Reward Types

Reward users with points for completing actions.
amount
number
required
The number of points to reward.
loyaltyCurrencyId
string
required
ID of the currency to reward with.

Rule Types

Rule types are grouped below to match the categories shown in the loyalty dashboard. Each type only reads the metadata (and top-level) fields listed for it — omit the rest.

User Onboarding

Complete Profile Details (profile_completed)

Reward users for completing their profile.
metadata.completeProfileConditions
Record<string, boolean>
Which profile fields must be filled. Keys: profile_picture, name, location, nft_portfolio, about, email, twitter, discord, telegram, evm, solana, sui, ton, imx. If omitted, a default set is checked (bio, avatar, X, Discord, email).

Refer a Friend (referred_user)

Reward users for referring others.
amount
number
required
Points for the referred user.
metadata.referrerReward
number
required
Points for the referrer.
metadata.referrerRewardLoyaltyCurrencyId
string
Currency for referrer reward.
metadata.referralRequirements.achievePoints
boolean
Require referred users to achieve points.
metadata.referralRequirements.points.amount
number
Required points when achievePoints is true.
metadata.referralRequirements.completeProfile
boolean
Require complete profile.
metadata.referralRequirements.connectTwitter
boolean
Require Twitter connection.
metadata.referralRequirements.connectDiscord
boolean
Require Discord connection.
metadata.referralRequirements.connectEmail
boolean
Require email connection.

Check In (check_in)

Reward users for checking in.
amount
number
required
Points for each check-in.
metadata.enableStreaks
boolean
Enable streak tracking for consecutive check-ins.
metadata.streakArray
Array<Streak>
Optional array of streak milestones and rewards.
streakMilestone
number
required
Number of consecutive days for this streak.
streakAmount
number
required
Points awarded for reaching this milestone.

Connect Accounts

Reward users for connecting an account. Most connection rules need no metadata — pass an empty object "metadata": {}.
Rule typeMetadata
connected_emailNone — pass {}
connected_phoneNone — pass {}
connected_telegramNone — pass {}
connected_tiktokNone — pass {}
connected_githubNone — pass {}
connected_youtubeNone — pass {}
connected_redditNone — pass {}
connected_instagramNone — pass {}
connected_steamNone — pass {}
connected_epicNone — pass {}
The remaining connection rules take metadata:

Connect X (connected_twitter)

metadata.enableVerifiedMultiplier
boolean
Apply a higher reward to verified (blue-check) accounts.
metadata.verifiedMultiplier
number
Multiplier applied when enableVerifiedMultiplier is true (e.g. 1.5).

Connect Discord (connected_discord)

metadata.enableJoinDiscordServers
boolean
Require users to also join specific Discord servers.
metadata.discordServersToJoin
Array<DiscordServer>
Servers (and optionally channels/roles) users must join.
id
string
required
Discord server ID.
channels
Array<Channel>
Channels to verify activity in.
roles
Array<Role>
Optional roles to verify.

Connect Wallet (connect_wallet)

metadata.walletType
WalletType
required
Which wallet type the user must connect (e.g. evm, solana).

Social Quests

X (Twitter) engagement rules generally require oauthCredentialsId (top-level) so the platform can verify activity, and many accept an optional verified-account multiplier (metadata.enableVerifiedMultiplier, metadata.verifiedMultiplier).

React to an X Post (drip_x_tweet)

metadata.twitterPostUrl
string
required
URL of the X post to engage with.
metadata.twitterUserId
string
required
Twitter user ID of the post author.
metadata.checkLike
boolean
Require liking the post.
metadata.checkRepost
boolean
Require reposting.
metadata.checkComment
boolean
Require commenting.
oauthCredentialsId
string
Twitter OAuth credentials (top-level field).

Post on X (drip_x_new_tweet)

metadata.checkText
string | Array<string>
Text that must be included in the tweet.
metadata.requirePostLink
boolean
Require users to submit post link (default: true).
metadata.requirePostMediaLink
boolean
Require post to include media.

Follow an X Account (drip_x_follow, twitter_follow)

metadata.twitterUsername
string
required
X account to follow.
metadata.twitterUserId
string
required
Twitter user ID of the account.
oauthCredentialsId
string
required
OAuth credentials for Twitter (top-level field).
drip_x_follow accepts the account as metadata.twitterAccountUrl (full profile URL) instead of username/ID.

Add Text to X Bio / Username / Comment (drip_x_text_in_bio, drip_x_text_in_name, drip_x_text_in_comment)

metadata.checkText
string | Array<string>
required
Text that must appear in the user’s bio, display name, or comment.
metadata.rewardQualityPosts
boolean
(drip_x_text_in_comment) Only reward posts that pass quality/sentiment checks.
metadata.minimumFollowerCount
number
(drip_x_text_in_comment) Minimum follower count to qualify.

Reach X Followers (twitter_followers)

metadata.range
Array<RewardAmountRange>
required
Tiered rewards by the user’s follower count.

Get X Post Impressions (post_impressions)

metadata.range
Array<RewardAmountRange>
required
Tiered rewards by post view/impression count.
metadata.rewardQualityPosts
boolean
Only reward posts that pass quality/sentiment checks.
metadata.minimumFollowerCount
number
Minimum follower count to qualify.
trackProgress
boolean
Optional top-level flag to track progress. mediaUrl (top-level) can supply a media reference.

Repost an X Post (Retweet)

metadata.twitterUserId
string
required
Twitter user ID of the account whose posts are monitored for reposts.

Like an X Post (twitter_like)

metadata.twitterUsername
string
required
Account that posted the tweet.
metadata.twitterUserId
string
required
Twitter user ID.
oauthCredentialsId
string
required
OAuth credentials (top-level field).

Comment on an X Post (twitter_comment)

metadata.twitterUserId
string
required
Twitter user ID of the account whose posts are monitored for comments.

Post on X with Hashtag (twitter_post_hashtag)

metadata.twitterHashtag
string
required
Hashtag to search for in recent posts.

Get an X Post Liked by Project (tweet_liked_by_project)

metadata.twitterUserId
string
required
Twitter user ID of the project account whose like qualifies the user.
oauthCredentialsId
string
required
OAuth credentials for Twitter (top-level field).
metadata.rewardPerImpression
boolean
Multiply the reward by the tweet’s impression count.

Get Discord Role (discord_member)

metadata.discordServersToJoin
Array<DiscordServer>
required
Servers and roles to verify. Each item uses id and roles.

Join Discord Server (discord_join)

metadata.discordServersToJoin
Array<DiscordServer>
required
Servers the user must join. Only the server id is required for this type.

Send Discord Messages (DiscordMessages)

metadata.discordServersToJoin
Array<DiscordServer>
required
Server id and the channels whose messages count. Each channel can specify text to match and emojis reactions.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards based on message count.

Grant a Discord Role (discord_role_grant)

metadata.discordServersToJoin
Array<DiscordServer>
required
Server id plus the roles to grant. roles is required for this type.
id
string
required
Discord server (guild) ID.
channels
Array<Channel>
Channels to check. Each: { id: string, text?: string, emojis?: Array<{ id: string }> }. Used by DiscordMessages.
roles
Array<{ id: string }>
Roles to verify or grant. Required for discord_role_grant.

Join Telegram Group (telegram_join)

metadata.telegramChannelId
string
required
ID of the Telegram channel the user must join.

Send Telegram Messages (telegram_messages)

metadata.telegramChannelId
string
required
ID of the Telegram channel whose messages count.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards based on message count.

Follow a TikTok Account (tiktok_follow)

metadata.twitterAccountUrl
string
required
TikTok profile URL to follow (e.g. https://www.tiktok.com/@username). Despite the field name, this holds the TikTok URL.

Post on TikTok (tiktok_post)

metadata.checkText
string | Array<string>
Text to check in post.
metadata.requirePostLink
boolean
Require post link submission.
metadata.rewardCriteria
LoyaltyPostRewardCriteria
IMPRESSIONS_COUNT or ELIGIBLE_POST.

Post on Instagram (instagram_post)

metadata.checkText
string | Array<string>
required
Text or hashtag the post must include.
metadata.rewardQualityPosts
boolean
Only reward posts that pass quality checks.
metadata.minimumFollowerCount
number
Minimum follower count to qualify.

Follow an Instagram Account (instagram_follow)

metadata.twitterAccountUrl
string
required
Instagram profile URL to follow (e.g. https://www.instagram.com/username). Despite the field name, this holds the Instagram URL.

Subscribe to a YouTube Channel (youtube_subscribers)

metadata.youtubeChannelId
string
required
YouTube channel ID the user must subscribe to.
externalIntegrationId
string
Optional Google API integration ID (top-level field) used for verification.

Comment on a YouTube Video (youtube_comment)

metadata.youtubeVideoId
string
required
YouTube video ID the user must comment on.
externalIntegrationId
string
Optional Google API integration ID (top-level field) used for verification.

Comment on a Reddit Post (reddit_comment)

metadata.redditPostId
string
required
ID of the Reddit post users must comment on.
metadata.cta.href
string
required
Full URL of the Reddit post.

Add an Item to Steam Wishlist (steam_wishlist)

metadata.steamAppId
string
required
Steam application ID the user must wishlist.

Spend in Shopify Store (shopify_spend)

shopifyStoreUrl
string
required
Shopify store domain (top-level field).
shopifyStoreAccessToken
string
required
Shopify admin API access token (top-level field).
metadata.range
Array<RewardAmountRange>
Range-based rewards by purchase amount.

Token Activity

Mint an NFT (MintOn)

Reward users for minting NFTs.
collections
Array<Collection>
required
Collections to track (top-level field).
metadata.hasNeverSold
boolean
Only reward users who have never sold the token.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards.

Purchase an NFT (BoughtOn)

Reward users for purchasing NFTs.
collections
Array<Collection>
required
Collections to track (top-level field).
metadata.onlyRewardExistingUser
boolean
Only reward existing users.
metadata.hasNeverSold
boolean
Only reward users who never sold the token.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards.
{
  "name": "NFT Purchase Rewards",
  "type": "BoughtOn",
  "network": "mainnet",
  "collections": [{ "address": "0x...", "network": "mainnet" }],
  "frequency": "daily",
  "interval": "once",
  "startTime": "2024-01-01T00:00:00Z",
  "rewardType": "points",
  "loyaltyCurrencyId": "currency_123",
  "amount": 1000,
  "metadata": {
    "onlyRewardExistingUser": false,
    "hasNeverSold": false
  }
}

Hold an NFT (TokenHold)

Reward users for holding specific NFTs.
collections
Array<Collection>
required
Collections to track (top-level field).
metadata.onlyRewardExistingUser
boolean
Only reward existing users.
metadata.onlyRewardSingleTokenOwnership
boolean
Reward only one token ownership per contract.
metadata.range
Array<RewardAmountRange>
Tiered rewards by number of tokens held.
{
  "name": "Hold Blue Chip NFT",
  "type": "TokenHold",
  "network": "mainnet",
  "collections": [
    {
      "address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
      "network": "mainnet"
    }
  ],
  "frequency": "daily",
  "interval": "daily",
  "startTime": "2024-01-01T00:00:00Z",
  "rewardType": "points",
  "loyaltyCurrencyId": "currency_123",
  "amount": 100,
  "metadata": {
    "onlyRewardExistingUser": false,
    "onlyRewardSingleTokenOwnership": false
  }
}

Sell an NFT (SoldOn)

Reward users for selling NFTs.
metadata.hasSaleCurrency
boolean
Filter by specific sale currency.
metadata.saleCurrency
string
Currency address when hasSaleCurrency is true.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards.

Hold a Fungible Token (token_hold_erc20)

Reward users for holding ERC20 tokens.
metadata.rewardPerValue
boolean
Reward based on USD value held rather than token count.
metadata.isTokenHoldMultiplier
boolean
Apply a multiplier per holding tier instead of fixed points.
metadata.range
Array<RewardAmountRange>
Tiered rewards by amount held.

Swap a Token (swap)

Reward users for token swaps.
metadata.swap.provider
string
any, relay, or lifi.
metadata.swap.relayReferrerId
string
Relay referrer ID when provider is relay.
metadata.swap.from
object
Source-token filter: { mode: "any" | "specific", chain, tokens, trackAmount }.
metadata.swap.to
object
Destination-token filter: { mode: "any" | "specific", chain, tokens, trackAmount }.
metadata.swap.requireCrossChainSwap
boolean
Require cross-chain swaps.

Hold tokens in Robinhood (robinhood_token_hold)

metadata.robinhoodSymbols
Array<string>
required
Token symbols to track (e.g. ["TRUMP", "SPY"]).
metadata.range
Array<RewardAmountRange>
Optional tiered rewards by holding amount. Falls back to top-level amount if omitted.

Complex Onchain Logic

Smart Contract Event (smart_contract_event)

Reward based on smart contract events.
collectionAddress
string
required
Contract address to monitor (top-level field).
metadata.smartContract.event
string
Event signature to track.
metadata.smartContract.criteria
SmartContractCriteria
everyEvent or specify conditions.
metadata.smartContract.params
Array<Param>
Event parameter filters.
metadata.smartContract.addressMapping
string
Address parameter name in event.

Stratus Function (stratus_function)

Custom on-chain logic executed by a Stratus function; the function controls reward output.
functionId
string
required
ID of the Stratus function to run (top-level field).
subscriptionId
string
Optional Stratus subscription ID (top-level field).
isDappRule
boolean
Optionally route rewards to the dApp owner. When true, rewardType must be points and network is required.

Provide Liquidity on Uniswap V2 / V3 (liquidity_uniswap_v2, liquidity_uniswap_v3)

metadata.liquidity.network
NetworkType
required
Chain for liquidity pools.
metadata.liquidity.protocol
string
required
Protocol identifier (e.g., “uniswap-v2/eth-usdc”).
metadata.liquidity.pools
Array<Pool>
Array of liquidity pool addresses (max 20, same network/protocol).
metadata.liquidity.calculationType
LiquidityCalculationType
required
fixed or custom.
metadata.liquidity.liquidityPerDay
number
USD value per day (when calculationType is fixed).
metadata.liquidity.customFunction
string
Custom calculation formula (when calculationType is custom).

Developers Contribution

Star / Fork / Become a Collaborator (github_repo_star, github_repo_fork, github_repo_collaborator)

metadata.githubRepoUrl
string
required
Repository URL. Must match https://github.com/<owner>/<repo>.

Merge a GitHub PR (github_merge_PR)

metadata.githubRepoUrl
string
required
Repository URL. Must match https://github.com/<owner>/<repo>.
metadata.githubBranchName
string
Target branch to count merged PRs against. Defaults to main if omitted.
metadata.range
Array<RewardAmountRange>
Optional tiered rewards by number of merged PRs.

Other

Submit Text Input (text_input)

metadata.verifyPlaceHolderText
string
Placeholder text for the input field.
metadata.verificationTextMinimumLength
number
Minimum character length required.

Enter a Code (code_entry)

Reward users for entering promo codes.
metadata.promoCodeType
PromoCodeType
required
Type: code, csv, or generate.
metadata.promoCode
string
Single shared code (when promoCodeType is code).
metadata.promoCodeCsvUrl
string
CSV URL with unique codes (when promoCodeType is csv).
metadata.promoCodeLength
number
Number of codes to generate (when promoCodeType is generate).
metadata.isRestrictedToNewUsers
boolean
Only allow new users (last 6 hours) to redeem.
URL the user clicks.
metadata.timeDelayToVerifySeconds
number
Delay (1–600 s) before the reward is granted.
metadata.socialPlatform
SocialPlatform
Platform shown for the link (e.g. X, Discord, or Custom).
metadata.buttonText
string
Label on the action button.

Answer a Quiz (quiz)

question.text
string
required
Question text.
question.choices
Array<Choice>
Answer options with isCorrect flag. Exactly one choice must be correct.

Answer a Poll (poll)

question.text
string
required
Poll question text.
question.choices
Array<Choice>
Answer choices.
question.allowMultipleAttempts
boolean
Allow users to vote multiple times.

Participate in Governance Vote (snapshot_governance)

metadata.snapshotProposals
Array<{ id: string, space: string }>
required
Snapshot proposal(s) to track. One proposal per rule.

Create a Partner Account (create_partner_account)

Partner site URL. Must match the partner auth domain.
metadata.buttonText
string
Label on the action button.

External Rule (external_rule)

Custom rules managed by external services.
amount
number
required
Base points amount.
trackProgress
boolean
Track completion progress (top-level field).
metadata.range
Array<RewardAmountRange>
Range-based rewards with custom amounts.
metadata.rewardPerAction
boolean
Multiply reward by number of actions.
metadata.conditionDescription
string
Description of what the external rule tracks.

Points Airdrop (points_airdrop)

Airdrop points to specific users via CSV.
loyaltyUserAllotmentCsvUrl
string
required
CSV URL with wallet addresses and point amounts (top-level field).
trackProgress
boolean
Track processing progress.

dApp Activity

Rank and reward dApps by on-chain activity. These rules rely on several top-level fields in addition to metadata.range, and route rewards to the dApp owner (isDappRule). Applies to: dapps_by_gas_spent, dapps_by_active_users, dapps_by_new_users, dapps_by_transaction_count.
metadata.range
Array<RewardAmountRange>
required
Tiered rewards by rank/threshold for the chosen metric.
dappDataWindow
LoyaltyRuleInterval
required
Data window for the metric: daily, weekly, or monthly. Leave empty for all-time.
dappDeployedWithin
LoyaltyRuleInterval
Optional filter limiting to dApps deployed within this window.
isDappRule
boolean
Routes rewards to the dApp owner. Immutable after creation.
network
NetworkType
required
Blockchain network for the rule (required when isDappRule is true).
dapps_by_user_retention appears in the dashboard but is not yet implemented — creating it will fail. Use one of the four supported dApp metrics above.

Range-Based Rewards

Some rules support range-based rewards with tiered amounts:
metadata.range
Array<RewardAmountRange>
Array of reward ranges.
startRange
number
required
Minimum value for this range.
endRange
number
required
Maximum value (use Number.MAX_SAFE_INTEGER for unlimited).
amount
number
required
Points awarded for this range.
loyaltyBadgeId
string
Optional badge for this range.

Range Examples

"metadata": {
  "range": [
    {
      "startRange": 1,
      "endRange": 10,
      "amount": 100
    },
    {
      "startRange": 11,
      "endRange": 50,
      "amount": 500
    },
    {
      "startRange": 51,
      "endRange": 9223372036854775807,
      "amount": 1000
    }
  ]
}
"metadata": {
  "range": [
    {
      "startRange": 1,
      "endRange": 9223372036854775807,
      "amount": 1.5
    }
  ],
  "isTokenHoldMultiplier": true
}

Advanced Configuration

Max Reward Limits

maxAmountPerInterval
number
Maximum points users can earn in the interval.
maxAmountInterval
LoyaltyRuleMaxAmountInterval
Interval period: daily, weekly, monthly.

Claim Type

claimType
LoyaltyRuleClaimType
manual (user must claim) or auto (auto-rewarded).

Reward Lifetime

rewardLifetime
LoyaltyRuleRewardLifetime
For multipliers/badges: permanent (never removed) or dynamic (removed if requirements not met).

Airdrop Duration

effectiveStartTime
ISO8601
When airdrop becomes effective.
effectiveEndTime
ISO8601
When airdrop ends.

Validation Examples

{
  "organizationId": "org_123",
  "websiteId": "website_456",
  "name": "Daily Login",
  "type": "check_in",
  "frequency": "daily",
  "interval": "daily",
  "startTime": "2024-01-01T00:00:00Z",
  "rewardType": "points",
  "amount": 10,
  "loyaltyCurrencyId": "currency_789",
  "network": "ethereum",
  "metadata": {}
}
{
  "organizationId": "org_123",
  "websiteId": "website_456",
  "name": "Hold Premium NFT",
  "type": "TokenHold",
  "network": "mainnet",
  "collections": [{
    "address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
    "network": "mainnet"
  }],
  "frequency": "daily",
  "interval": "daily",
  "startTime": "2024-01-01T00:00:00Z",
  "endTime": "2024-12-31T23:59:59Z",
  "rewardType": "points",
  "amount": 100,
  "loyaltyCurrencyId": "currency_789",
  "metadata": {
    "hasCustomRewardsUrl": true,
    "customRewardsApiUrl": "https://api.example.com/rewards",
    "customRewardsApiKey": "key_xyz"
  }
}
{
  "organizationId": "org_123",
  "websiteId": "website_456",
  "name": "Tweet Challenge",
  "type": "drip_x_new_tweet",
  "network": "ethereum",
  "frequency": "daily",
  "interval": "unlimited",
  "startTime": "2024-01-01T00:00:00Z",
  "rewardType": "points",
  "loyaltyCurrencyId": "currency_789",
  "metadata": {
    "checkText": ["#project", "launch"],
    "requirePostLink": true,
    "requirePostMediaLink": false,
    "range": [
      {
        "startRange": 1,
        "endRange": 5,
        "amount": 10
      },
      {
        "startRange": 6,
        "endRange": 20,
        "amount": 50
      },
      {
        "startRange": 21,
        "endRange": 9223372036854775807,
        "amount": 100
      }
    ]
  }
}

Error Handling

All required fields must be provided. Missing required fields will result in a 400 Bad Request error with details about which fields are missing.
Range values must not overlap. The start range should be less than or equal to the end range for each range entry.
For Ultra networks (Ultra/UltraTestnet), the collection address format is address::symbol. For example: accountname::TOKEN.
Use the loyaltyCurrencyId field consistently across rules to ensure proper currency management in your loyalty program.

Rule Type Limitations and Restrictions

Multiplier Reward Type Support

The multiplier reward type is NOT supported for the following rule types:
  • check_in
  • link_click
  • referred_user
  • points_airdrop
Only points and badge reward types are available for these rules.

Claim Type Support

Different rule types support different claim types (manual vs auto-reward):
These rules require users to manually claim rewards:
  • check_in
  • text_input
  • poll
  • quiz
  • create_partner_account
  • telegram_join
  • drip_x_follow
  • drip_x_tweet
  • drip_x_new_tweet
  • swap

Reward Lifetime Options

The rewardLifetime field (for multipliers and badges) has different support levels:
Most rules only support permanent lifetime where rewards never expire:
  • check_in
  • twitter_followers
  • Retweet
  • BoughtOn, SoldOn, MintOn
  • twitter_like, twitter_comment, twitter_post_hashtag
  • profile_completed, referred_user
  • poll, quiz
  • Most social and connection rules
With permanent lifetime, once a user qualifies for the reward, they keep it forever even if they stop meeting requirements.
These rules support both permanent and dynamic lifetime:
  • TokenHold - Most flexible, supports both
  • external_rule - Can expire if user stops meeting requirements
With dynamic lifetime, rewards are removed if the user no longer meets the requirements (e.g., sold their NFT).

Interval Restrictions

Some rules have limited interval options:
Rules with frequency: immediately typically only support interval: once or specific intervals.Rules with frequency: none may support custom intervals.

Range-Based Rewards

Range-based rewards are ONLY supported for:
  • TokenHold
  • BoughtOn, SoldOn, MintOn
  • token_hold_erc20
  • twitter_followers (with rewardCriteria)
  • external_rule (with trackProgress)
  • shopify_spend
Range-based rewards require the metadata.range array. Maximum range value is Number.MAX_SAFE_INTEGER (use this for unlimited).

Network-Specific Limitations

For Ultra and UltraTestnet networks, collection addresses require a symbol suffix: address::symbol (e.g., accountname::TOKEN)

Token Holdings

ERC20 token holding rules (token_hold_erc20) require network support for USD price tracking. Networks without USD support will disable the rewardPerValue option.

Liquidity Pool Limits

Liquidity rules support a maximum of 20 pools per rule, all within the same network and protocol with the same factory address.

Shopify Integration

Shopify spend rules require providing both shopifyStoreUrl and shopifyStoreAccessToken. The access token is used for one-time authentication during rule creation but is not stored.