Create loyalty rules using API
Learn how to create different types of loyalty rules through the API with the correct parameters and metadata
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:
organizationIdstringrequiredThe organization ID that owns this rule.
websiteIdstringrequiredThe website ID where this rule will be applied.
namestringrequiredThe name of the loyalty rule (max 255 characters).
descriptionstringOptional description of the rule.
typeLoyaltyRuleTyperequiredThe type of loyalty rule. See available types below.
frequencyLoyaltyRuleFrequencyrequiredHow often eligibility is checked. Options: once, daily, weekly,
monthly, immediately.
intervalLoyaltyRuleIntervalHow often users can earn rewards. Options: once, daily, weekly,
monthly, unlimited, custom.
startTimeISO8601 stringrequiredWhen the rule becomes active (ISO 8601 format).
endTimeISO8601 stringOptional end time for the rule (ISO 8601 format).
rewardTypeLoyaltyRuleRewardTyperequiredType of reward: points, multiplier, or badge.
loyaltyCurrencyIdstringrequiredThe ID of the loyalty currency (points) to reward.
networkNetworkTyperequiredThe blockchain network. Options: mainnet, goerli, polygon, arbitrum,
etc.
Reward Configuration
Reward Types
Reward users with points for completing actions.
amountnumberrequiredThe number of points to reward.
loyaltyCurrencyIdstringrequiredID 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.completeProfileConditionsRecord<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.
amountnumberrequiredPoints for the referred user.
metadata.referrerRewardnumberrequiredPoints for the referrer.
metadata.referrerRewardLoyaltyCurrencyIdstringCurrency for referrer reward.
metadata.referralRequirements.achievePointsbooleanRequire referred users to achieve points.
metadata.referralRequirements.points.amountnumberRequired points when achievePoints is true.
metadata.referralRequirements.completeProfilebooleanRequire complete profile.
metadata.referralRequirements.connectTwitterbooleanRequire Twitter connection.
metadata.referralRequirements.connectDiscordbooleanRequire Discord connection.
metadata.referralRequirements.connectEmailbooleanRequire email connection.
Check In (check_in)
Reward users for checking in.
amountnumberrequiredPoints for each check-in.
metadata.enableStreaksbooleanEnable streak tracking for consecutive check-ins.
metadata.streakArrayArray<Streak>Optional array of streak milestones and rewards.
streakMilestonenumberrequiredNumber of consecutive days for this streak.
streakAmountnumberrequiredPoints 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 type | Metadata |
|---|---|
connected_email | None — pass {} |
connected_phone | None — pass {} |
connected_telegram | None — pass {} |
connected_tiktok | None — pass {} |
connected_github | None — pass {} |
connected_youtube | None — pass {} |
connected_reddit | None — pass {} |
connected_instagram | None — pass {} |
connected_steam | None — pass {} |
connected_epic | None — pass {} |
The remaining connection rules take metadata:
Connect X (connected_twitter)
metadata.enableVerifiedMultiplierbooleanApply a higher reward to verified (blue-check) accounts.
metadata.verifiedMultipliernumberMultiplier applied when enableVerifiedMultiplier is true (e.g. 1.5).
Connect Discord (connected_discord)
metadata.enableJoinDiscordServersbooleanRequire users to also join specific Discord servers.
metadata.discordServersToJoinArray<DiscordServer>Servers (and optionally channels/roles) users must join.
idstringrequiredDiscord server ID.
channelsArray<Channel>Channels to verify activity in.
rolesArray<Role>Optional roles to verify.
Connect Wallet (connect_wallet)
metadata.walletTypeWalletTyperequiredWhich 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.twitterPostUrlstringrequiredURL of the X post to engage with.
metadata.twitterUserIdstringrequiredTwitter user ID of the post author.
metadata.checkLikebooleanRequire liking the post.
metadata.checkRepostbooleanRequire reposting.
metadata.checkCommentbooleanRequire commenting.
oauthCredentialsIdstringTwitter OAuth credentials (top-level field).
Post on X (drip_x_new_tweet)
metadata.checkTextstring | Array<string>Text that must be included in the tweet.
metadata.requirePostLinkbooleanRequire users to submit post link (default: true).
metadata.requirePostMediaLinkbooleanRequire post to include media.
Follow an X Account (drip_x_follow, twitter_follow)
metadata.twitterUsernamestringrequiredX account to follow.
metadata.twitterUserIdstringrequiredTwitter user ID of the account.
oauthCredentialsIdstringrequiredOAuth 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.checkTextstring | Array<string>requiredText that must appear in the user's bio, display name, or comment.
metadata.rewardQualityPostsboolean(drip_x_text_in_comment) Only reward posts that pass quality/sentiment
checks.
metadata.minimumFollowerCountnumber(drip_x_text_in_comment) Minimum follower count to qualify.
Reach X Followers (twitter_followers)
metadata.rangeArray<RewardAmountRange>requiredTiered rewards by the user's follower count.
Get X Post Impressions (post_impressions)
metadata.rangeArray<RewardAmountRange>requiredTiered rewards by post view/impression count.
metadata.rewardQualityPostsbooleanOnly reward posts that pass quality/sentiment checks.
metadata.minimumFollowerCountnumberMinimum follower count to qualify.
trackProgressbooleanOptional top-level flag to track progress. mediaUrl (top-level) can supply a
media reference.
Repost an X Post (Retweet)
metadata.twitterUserIdstringrequiredTwitter user ID of the account whose posts are monitored for reposts.
Like an X Post (twitter_like)
metadata.twitterUsernamestringrequiredAccount that posted the tweet.
metadata.twitterUserIdstringrequiredTwitter user ID.
oauthCredentialsIdstringrequiredOAuth credentials (top-level field).
Comment on an X Post (twitter_comment)
metadata.twitterUserIdstringrequiredTwitter user ID of the account whose posts are monitored for comments.
Post on X with Hashtag (twitter_post_hashtag)
metadata.twitterHashtagstringrequiredHashtag to search for in recent posts.
Get an X Post Liked by Project (tweet_liked_by_project)
metadata.twitterUserIdstringrequiredTwitter user ID of the project account whose like qualifies the user.
oauthCredentialsIdstringrequiredOAuth credentials for Twitter (top-level field).
metadata.rewardPerImpressionbooleanMultiply the reward by the tweet's impression count.
Get Discord Role (discord_member)
metadata.discordServersToJoinArray<DiscordServer>requiredServers and roles to verify. Each item uses id and roles.
Join Discord Server (discord_join)
metadata.discordServersToJoinArray<DiscordServer>requiredServers the user must join. Only the server id is required for this type.
Send Discord Messages (DiscordMessages)
metadata.discordServersToJoinArray<DiscordServer>requiredServer id and the channels whose messages count. Each channel can specify
text to match and emojis reactions.
metadata.rangeArray<RewardAmountRange>Optional tiered rewards based on message count.
Grant a Discord Role (discord_role_grant)
metadata.discordServersToJoinArray<DiscordServer>requiredServer id plus the roles to grant. roles is required for this type.
idstringrequiredDiscord server (guild) ID.
channelsArray<Channel>Channels to check. Each: { id: string, text?: string, emojis?: Array<{ id: string }> }. Used by DiscordMessages.
rolesArray<{ id: string }>Roles to verify or grant. Required for discord_role_grant.
Join Telegram Group (telegram_join)
metadata.telegramChannelIdstringrequiredID of the Telegram channel the user must join.
Send Telegram Messages (telegram_messages)
metadata.telegramChannelIdstringrequiredID of the Telegram channel whose messages count.
metadata.rangeArray<RewardAmountRange>Optional tiered rewards based on message count.
Follow a TikTok Account (tiktok_follow)
metadata.twitterAccountUrlstringrequiredTikTok 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.checkTextstring | Array<string>Text to check in post.
metadata.requirePostLinkbooleanRequire post link submission.
metadata.rewardCriteriaLoyaltyPostRewardCriteriaIMPRESSIONS_COUNT or ELIGIBLE_POST.
Post on Instagram (instagram_post)
metadata.checkTextstring | Array<string>requiredText or hashtag the post must include.
metadata.rewardQualityPostsbooleanOnly reward posts that pass quality checks.
metadata.minimumFollowerCountnumberMinimum follower count to qualify.
Follow an Instagram Account (instagram_follow)
metadata.twitterAccountUrlstringrequiredInstagram 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.youtubeChannelIdstringrequiredYouTube channel ID the user must subscribe to.
externalIntegrationIdstringOptional Google API integration ID (top-level field) used for verification.
Comment on a YouTube Video (youtube_comment)
metadata.youtubeVideoIdstringrequiredYouTube video ID the user must comment on.
externalIntegrationIdstringOptional Google API integration ID (top-level field) used for verification.
Comment on a Reddit Post (reddit_comment)
metadata.redditPostIdstringrequiredID of the Reddit post users must comment on.
metadata.cta.hrefstringrequiredFull URL of the Reddit post.
Add an Item to Steam Wishlist (steam_wishlist)
metadata.steamAppIdstringrequiredSteam application ID the user must wishlist.
Spend in Shopify Store (shopify_spend)
shopifyStoreUrlstringrequiredShopify store domain (top-level field).
shopifyStoreAccessTokenstringrequiredShopify admin API access token (top-level field).
metadata.rangeArray<RewardAmountRange>Range-based rewards by purchase amount.
Token Activity
Mint an NFT (MintOn)
Reward users for minting NFTs.
collectionsArray<Collection>requiredCollections to track (top-level field).
metadata.hasNeverSoldbooleanOnly reward users who have never sold the token.
metadata.rangeArray<RewardAmountRange>Optional tiered rewards.
Purchase an NFT (BoughtOn)
Reward users for purchasing NFTs.
collectionsArray<Collection>requiredCollections to track (top-level field).
metadata.onlyRewardExistingUserbooleanOnly reward existing users.
metadata.hasNeverSoldbooleanOnly reward users who never sold the token.
metadata.rangeArray<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.
collectionsArray<Collection>requiredCollections to track (top-level field).
metadata.onlyRewardExistingUserbooleanOnly reward existing users.
metadata.onlyRewardSingleTokenOwnershipbooleanReward only one token ownership per contract.
metadata.rangeArray<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.hasSaleCurrencybooleanFilter by specific sale currency.
metadata.saleCurrencystringCurrency address when hasSaleCurrency is true.
metadata.rangeArray<RewardAmountRange>Optional tiered rewards.
Hold a Fungible Token (token_hold_erc20)
Reward users for holding ERC20 tokens.
metadata.rewardPerValuebooleanReward based on USD value held rather than token count.
metadata.isTokenHoldMultiplierbooleanApply a multiplier per holding tier instead of fixed points.
metadata.rangeArray<RewardAmountRange>Tiered rewards by amount held.
Swap a Token (swap)
Reward users for token swaps.
metadata.swap.providerstringany, relay, or lifi.
metadata.swap.relayReferrerIdstringRelay referrer ID when provider is relay.
metadata.swap.fromobjectSource-token filter: { mode: "any" | "specific", chain, tokens, trackAmount }.
metadata.swap.toobjectDestination-token filter: { mode: "any" | "specific", chain, tokens, trackAmount }.
metadata.swap.requireCrossChainSwapbooleanRequire cross-chain swaps.
Hold tokens in Robinhood (robinhood_token_hold)
metadata.robinhoodSymbolsArray<string>requiredToken symbols to track (e.g. ["TRUMP", "SPY"]).
metadata.rangeArray<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.
collectionAddressstringrequiredContract address to monitor (top-level field).
metadata.smartContract.eventstringEvent signature to track.
metadata.smartContract.criteriaSmartContractCriteriaeveryEvent or specify conditions.
metadata.smartContract.paramsArray<Param>Event parameter filters.
metadata.smartContract.addressMappingstringAddress parameter name in event.
Stratus Function (stratus_function)
Custom on-chain logic executed by a Stratus function; the function controls reward output.
functionIdstringrequiredID of the Stratus function to run (top-level field).
subscriptionIdstringOptional Stratus subscription ID (top-level field).
isDappRulebooleanOptionally 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.networkNetworkTyperequiredChain for liquidity pools.
metadata.liquidity.protocolstringrequiredProtocol identifier (e.g., "uniswap-v2/eth-usdc").
metadata.liquidity.poolsArray<Pool>Array of liquidity pool addresses (max 20, same network/protocol).
metadata.liquidity.calculationTypeLiquidityCalculationTyperequiredfixed or custom.
metadata.liquidity.liquidityPerDaynumberUSD value per day (when calculationType is fixed).
metadata.liquidity.customFunctionstringCustom calculation formula (when calculationType is custom).
Developers Contribution
Star / Fork / Become a Collaborator (github_repo_star, github_repo_fork, github_repo_collaborator)
metadata.githubRepoUrlstringrequiredRepository URL. Must match https://github.com/<owner>/<repo>.
Merge a GitHub PR (github_merge_PR)
metadata.githubRepoUrlstringrequiredRepository URL. Must match https://github.com/<owner>/<repo>.
metadata.githubBranchNamestringTarget branch to count merged PRs against. Defaults to main if omitted.
metadata.rangeArray<RewardAmountRange>Optional tiered rewards by number of merged PRs.
Other
Submit Text Input (text_input)
metadata.verifyPlaceHolderTextstringPlaceholder text for the input field.
metadata.verificationTextMinimumLengthnumberMinimum character length required.
Enter a Code (code_entry)
Reward users for entering promo codes.
metadata.promoCodeTypePromoCodeTyperequiredType: code, csv, or generate.
metadata.promoCodestringSingle shared code (when promoCodeType is code).
metadata.promoCodeCsvUrlstringCSV URL with unique codes (when promoCodeType is csv).
metadata.promoCodeLengthnumberNumber of codes to generate (when promoCodeType is generate).
metadata.isRestrictedToNewUsersbooleanOnly allow new users (last 6 hours) to redeem.
Click a Link (link_click)
metadata.linkstringrequiredURL the user clicks.
metadata.timeDelayToVerifySecondsnumberDelay (1–600 s) before the reward is granted.
metadata.socialPlatformSocialPlatformPlatform shown for the link (e.g. X, Discord, or Custom).
metadata.buttonTextstringLabel on the action button.
Answer a Quiz (quiz)
question.textstringrequiredQuestion text.
question.choicesArray<Choice>Answer options with isCorrect flag. Exactly one choice must be correct.
Answer a Poll (poll)
question.textstringrequiredPoll question text.
question.choicesArray<Choice>Answer choices.
question.allowMultipleAttemptsbooleanAllow users to vote multiple times.
Participate in Governance Vote (snapshot_governance)
metadata.snapshotProposalsArray<{ id: string, space: string }>requiredSnapshot proposal(s) to track. One proposal per rule.
Create a Partner Account (create_partner_account)
metadata.linkstringrequiredPartner site URL. Must match the partner auth domain.
metadata.buttonTextstringLabel on the action button.
External Rule (external_rule)
Custom rules managed by external services.
amountnumberrequiredBase points amount.
trackProgressbooleanTrack completion progress (top-level field).
metadata.rangeArray<RewardAmountRange>Range-based rewards with custom amounts.
metadata.rewardPerActionbooleanMultiply reward by number of actions.
metadata.conditionDescriptionstringDescription of what the external rule tracks.
Points Airdrop (points_airdrop)
Airdrop points to specific users via CSV.
loyaltyUserAllotmentCsvUrlstringrequiredCSV URL with wallet addresses and point amounts (top-level field).
trackProgressbooleanTrack 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.rangeArray<RewardAmountRange>requiredTiered rewards by rank/threshold for the chosen metric.
dappDataWindowLoyaltyRuleIntervalrequiredData window for the metric: daily, weekly, or monthly. Leave empty for
all-time.
dappDeployedWithinLoyaltyRuleIntervalOptional filter limiting to dApps deployed within this window.
isDappRulebooleanRoutes rewards to the dApp owner. Immutable after creation.
networkNetworkTyperequiredBlockchain 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.rangeArray<RewardAmountRange>Array of reward ranges.
startRangenumberrequiredMinimum value for this range.
endRangenumberrequiredMaximum value (use Number.MAX_SAFE_INTEGER for unlimited).
amountnumberrequiredPoints awarded for this range.
loyaltyBadgeIdstringOptional 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
maxAmountPerIntervalnumberMaximum points users can earn in the interval.
maxAmountIntervalLoyaltyRuleMaxAmountIntervalInterval period: daily, weekly, monthly.
Claim Type
claimTypeLoyaltyRuleClaimTypemanual (user must claim) or auto (auto-rewarded).
Reward Lifetime
rewardLifetimeLoyaltyRuleRewardLifetimeFor multipliers/badges: permanent (never removed) or dynamic (removed if
requirements not met).
Airdrop Duration
effectiveStartTimeISO8601When airdrop becomes effective.
effectiveEndTimeISO8601When 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_inlink_clickreferred_userpoints_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_intext_inputpollquizcreate_partner_accounttelegram_joindrip_x_followdrip_x_tweetdrip_x_new_tweetswap
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_intwitter_followersRetweetBoughtOn,SoldOn,MintOntwitter_like,twitter_comment,twitter_post_hashtagprofile_completed,referred_userpoll,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 bothexternal_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:
TokenHoldBoughtOn,SoldOn,MintOntoken_hold_erc20twitter_followers(withrewardCriteria)external_rule(withtrackProgress)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.