Snag Docs logo

Create Loyalty Rule

Create a new Loyalty Rule

POSThttps://admin.snagsolutions.io/api/loyalty/rules

Create a new Loyalty Rule

Loading code example
Loading code example

Authorizations

apiKeyAuthstringheaderrequired

API key passed in the header.

Body

Body

organizationIdstring<uuid>required

Unique identifier for the organization creating the rule

websiteIdstring<uuid>required

Unique identifier for the associated website

backgroundAssetUrlstring

URL of the background asset to be displayed

namestringrequired

Name of the loyalty rule

Length: >= 1
descriptionstring

Optional detailed description of the rule

network"abstract" | "abstractTestnet" | "apechain" | "arbitrum" | "avalanche" | "avalancheFuji" | "base" | "baseSepolia" | "berachain" | "berachainArtio" | "berachainBepolia" | "binance" | "bscTestnet" | "campTestnet" | "fantom" | "fantomTestnet" | "flowMainnet" | "mainnet" | "nexus" | "nexusTestnet" | "optimism" | "polygon" | "polygon_mumbai" | "skaleNebula" | "skaleEuropa" | "skaleCalypso" | "solana" | "sophon" | "sophonTestnet" | "sui" | "superseed" | "superseedSepolia" | "vanar" | "xai" | "zksync" | "coti" | "cotiTestnet" | "dogeosTestnet" | "morph" | "morphTestnet" | "morphHolesky" | "ultra" | "ultraTestnet" | "nitrograph" | "sepolia" | "optimism_sepolia" | "arbitrumSepolia" | "goerli" | "optimism_goerli" | "arbitrumGoerli" | "basecamp" | "somnia" | "zkverify" | "polkadot" | "kusama" | "horizen" | "horizenTestnet" | "robinhoodChain" | "robinhoodChainTestnet" | "flow_cadence"

Blockchain network where the rule will apply

Allowed values: "abstract" | "abstractTestnet" | "apechain" | "arbitrum" | "avalanche" | "avalancheFuji" | "base" | "baseSepolia" | "berachain" | "berachainArtio" | "berachainBepolia" | "binance" | "bscTestnet" | "campTestnet" | "fantom" | "fantomTestnet" | "flowMainnet" | "mainnet" | "nexus" | "nexusTestnet" | "optimism" | "polygon" | "polygon_mumbai" | "skaleNebula" | "skaleEuropa" | "skaleCalypso" | "solana" | "sophon" | "sophonTestnet" | "sui" | "superseed" | "superseedSepolia" | "vanar" | "xai" | "zksync" | "coti" | "cotiTestnet" | "dogeosTestnet" | "morph" | "morphTestnet" | "morphHolesky" | "ultra" | "ultraTestnet" | "nitrograph" | "sepolia" | "optimism_sepolia" | "arbitrumSepolia" | "goerli" | "optimism_goerli" | "arbitrumGoerli" | "basecamp" | "somnia" | "zkverify" | "polkadot" | "kusama" | "horizen" | "horizenTestnet" | "robinhoodChain" | "robinhoodChainTestnet" | "flow_cadence"
Default: "mainnet"
type"Bonus" | "BoughtOn" | "BoughtWithRoyalties" | "DiscordMessages" | "Listing" | "Lodging" | "PoapClaim" | "SnagSocialsConnected" | "SnapshotFullset" | "SnapshotHold" | "SoldWithRoyalties" | "TwitterBio" | "TwitterHashTagPost" | "MintOn" | "SoldOn" | "TokenHold" | "Retweet" | "check_in" | "code_entry" | "connect_wallet" | "connected_discord" | "connected_email" | "connected_epic" | "connected_github" | "connected_steam" | "connected_telegram" | "connected_twitter" | "create_partner_account" | "discord_member" | "drip_x_follow" | "drip_x_new_tweet" | "drip_x_text_in_bio" | "drip_x_text_in_comment" | "drip_x_text_in_name" | "drip_x_tweet" | "external_rule" | "link_click" | "manual_upload" | "profile_completed" | "referred_user" | "smart_contract_event" | "snapshot_governance" | "telegram_join" | "telegram_messages" | "text_input" | "token_hold_erc20" | "tweet_liked_by_project" | "twitter_comment" | "twitter_follow" | "twitter_followers" | "twitter_like" | "twitter_post_hashtag" | "quiz" | "poll" | "steam_wishlist" | "liquidity_uniswap_v2" | "liquidity_uniswap_v3" | "points_airdrop" | "youtube_subscribers" | "youtube_comment" | "shopify_spend" | "swap" | "tiktok_post" | "post_impressions" | "discord_join" | "connected_youtube" | "stratus_function" | "connected_tiktok" | "tiktok_follow" | "github_repo_star" | "github_repo_fork" | "github_repo_collaborator" | "github_merge_PR" | "discord_role_grant" | "connected_reddit" | "reddit_comment" | "robinhood_token_hold" | "connected_instagram" | "instagram_post" | "instagram_follow" | "connected_phone" | "dapps_by_gas_spent" | "dapps_by_active_users" | "dapps_by_new_users" | "dapps_by_transaction_count" | "dapps_by_user_retention"required

Type of loyalty rule being created

Allowed values: "Bonus" | "BoughtOn" | "BoughtWithRoyalties" | "DiscordMessages" | "Listing" | "Lodging" | "PoapClaim" | "SnagSocialsConnected" | "SnapshotFullset" | "SnapshotHold" | "SoldWithRoyalties" | "TwitterBio" | "TwitterHashTagPost" | "MintOn" | "SoldOn" | "TokenHold" | "Retweet" | "check_in" | "code_entry" | "connect_wallet" | "connected_discord" | "connected_email" | "connected_epic" | "connected_github" | "connected_steam" | "connected_telegram" | "connected_twitter" | "create_partner_account" | "discord_member" | "drip_x_follow" | "drip_x_new_tweet" | "drip_x_text_in_bio" | "drip_x_text_in_comment" | "drip_x_text_in_name" | "drip_x_tweet" | "external_rule" | "link_click" | "manual_upload" | "profile_completed" | "referred_user" | "smart_contract_event" | "snapshot_governance" | "telegram_join" | "telegram_messages" | "text_input" | "token_hold_erc20" | "tweet_liked_by_project" | "twitter_comment" | "twitter_follow" | "twitter_followers" | "twitter_like" | "twitter_post_hashtag" | "quiz" | "poll" | "steam_wishlist" | "liquidity_uniswap_v2" | "liquidity_uniswap_v3" | "points_airdrop" | "youtube_subscribers" | "youtube_comment" | "shopify_spend" | "swap" | "tiktok_post" | "post_impressions" | "discord_join" | "connected_youtube" | "stratus_function" | "connected_tiktok" | "tiktok_follow" | "github_repo_star" | "github_repo_fork" | "github_repo_collaborator" | "github_merge_PR" | "discord_role_grant" | "connected_reddit" | "reddit_comment" | "robinhood_token_hold" | "connected_instagram" | "instagram_post" | "instagram_follow" | "connected_phone" | "dapps_by_gas_spent" | "dapps_by_active_users" | "dapps_by_new_users" | "dapps_by_transaction_count" | "dapps_by_user_retention"
frequency"none" | "once" | "hourly" | "daily" | "weekly" | "monthly" | "immediately"required

Execution frequency of the loyalty rule

Allowed values: "none" | "once" | "hourly" | "daily" | "weekly" | "monthly" | "immediately"
interval"hourly" | "daily" | "weekly" | "monthly" | "once" | "custom" | "every_message" | "unlimited"required

Interval between rule executions

Allowed values: "hourly" | "daily" | "weekly" | "monthly" | "once" | "custom" | "every_message" | "unlimited"
startTimestring<date-time>required

When the rule becomes active

endTimestring<date-time>required

When the rule becomes inactive

effectiveStartTimeanyrequired

The effective start time of the rule

effectiveEndTimeanyrequired

The effective end time of the rule

amountanyrequired

Reward amount associated with the rule

customRewardsCsvUrlstring<uri>

URL for uploading custom rewards via CSV

customRewardsApiUrlstring<uri>

URL for fetching custom rewards

subscriptionIdstring

Optional stratus subscription id for the rule

functionIdstring

Optional stratus function id for the rule

metadataobjectrequired

Additional metadata for the loyalty rule

metadata.isCheckInOnEveryTxnboolean

If enabled, the first transaction done on the platform will complete this rule

metadata.hasPaidFullRoyaltyboolean

Indicates if the full royalty has been paid for items.

metadata.royaltyAddressstring

Wallet address of the user can only be used if userId is not provided

metadata.royaltyPercentagenumber

Royalty percentage of the item.

Required range: x >= 1, x <= 100
metadata.hasVerifiedTwitterboolean

Indicates if the user has a verified Twitter account.

metadata.onlyRewardExistingUserboolean

Indicates if only existing users are rewarded.

metadata.hasNeverSoldboolean

Indicates if the item has never been sold.

metadata.onlyNativeboolean

Flag indicating whether to include only native tokens.

metadata.hasFillSourceboolean

Flag indicating whether the fill source is included.

metadata.fillSourcestring

Fill source of the order for the token sale

metadata.liquidityobject

Liquidity pool details.

metadata.twitterUsernamestring

Twitter username of the user.

metadata.twitterUserIdstring

Unique identifier of the Twitter user.

metadata.twitterHashtagstring

Hashtag associated with the Twitter post.

metadata.enableVerifiedMultiplierboolean

Flag indicating whether the verified multiplier is enabled.

metadata.verifiedMultipliernumber

Multiplier applied to rewards for verified users.

metadata.isMultiplierAppliedboolean

Indicates if the multiplier has been applied to rewards.

metadata.onlyKnownUsersboolean

Flag indicating whether to include only known users.

metadata.firstReferralRewardnumber

Percentage reward given to a user for their first referral.

metadata.referrerRewardnumber

Lump sum reward given to a referrer.

metadata.referrerRewardLoyaltyCurrencyIdstring

Loyalty currency ID of the referrer reward.

metadata.secondReferralRewardnumber

Percentage reward given for a second-level referral.

metadata.enableStreaksboolean

Flag indicating whether streaks are enabled.

metadata.promoCodestring

Promotional code associated with the rule.

metadata.promoCodeType"code" | "csv" | "generate"

Type of the promotional code.

Allowed values: "code" | "csv" | "generate"
metadata.promoCodeLengthnumber

Numbers of the promotional code to be generated.

metadata.promoCodeCsvUrlstring

URL of the CSV file containing promo codes.

metadata.enableJoinDiscordServersboolean

Flag indicating whether joining Discord servers is required.

metadata.discordServersToJoinarray<object>

Array of Discord servers, channels, and roles to join.

metadata.streakArrayarray<object>

Array of streak milestones and corresponding rewards.

metadata.dripQuestsToCompletearray<object>

Array of drip quests required to complete the rule.

metadata.collectionarray<object>

Array of collections associated with the rule.

metadata.rangearray<object>

Array defining ranges and corresponding rewards.

metadata.customRewardsApiKeystring

API key for custom rewards integration.

metadata.linkstring

Optional link associated with the metadata.

metadata.socialPlatform"Custom" | "Discord" | "EpicGames" | "Instagram" | "Phone" | "Steam" | "Telegram" | "TikTok" | "Twitch" | "X(Twitter)" | "YouTube" | "Google" | "GitHub" | "Reddit"

Social media platform associated with the rule.

Allowed values: "Custom" | "Discord" | "EpicGames" | "Instagram" | "Phone" | "Steam" | "Telegram" | "TikTok" | "Twitch" | "X(Twitter)" | "YouTube" | "Google" | "GitHub" | "Reddit"
metadata.socialPlatformNamestring

Name of the social platform.

metadata.socialPlatformLogostring

URL of the social platform's logo.

metadata.rewardPerImpressionboolean

Flag indicating if rewards are given per impression.

metadata.snapshotProposalsarray<object>

Array of snapshot proposals for the rule.

metadata.ctaobject

Object containing details for the call-to-action.

metadata.hasSaleCurrencyboolean

Flag indicating if the sale currency is included.

metadata.isTokenHoldMultiplierboolean

Flag indicating if the token hold multiplier is applied.

metadata.saleCurrencystring

Currency associated with sales.

metadata.isRetroactiveboolean

Flag indicating if rewards are applied retroactively.

metadata.timeDelayToVerifySecondsany

Time delay in seconds to verify actions.

metadata.referralRequirementsobject

Object defining referral requirements.

metadata.multiplierLoyaltyCurrencyIdsarray<string>

Array of loyalty currency IDs used for multipliers.

metadata.verifyPlaceHolderTextstring

Placeholder text for verification input fields.

metadata.verificationTextMinimumLengthinteger

Minimum length of the verification text.

metadata.buttonTextstring

Text displayed on the action button.

metadata.telegramChannelIdstring

ID of the Telegram channel.

metadata.twitterAccountUrlstring

URL of the associated Twitter account.

metadata.twitterPostUrlstring

URL of the associated Twitter post.

metadata.checkLikeboolean

Flag indicating if liking the post is required.

metadata.checkRepostboolean

Flag indicating if reposting is required.

metadata.checkCommentboolean

Flag indicating if commenting is required.

metadata.maxLikesinteger

Reaction limit for likes. Once the post reaches this many likes, the Like requirement is hidden from users. Likes are never verified server-side, so this only controls display.

Required range: x >= 1
metadata.maxRepostsinteger

Reaction limit for reposts. Once the post reaches this many reposts, the Repost requirement is hidden and no longer verified.

Required range: x >= 1
metadata.maxCommentsinteger

Reaction limit for comments. Once the post reaches this many comments, the Comment requirement is hidden and no longer verified.

Required range: x >= 1
metadata.reactionStatsobject

Latest scraped public reaction counts for the post, written back from social-service (throttled). Drives which reaction requirements are hidden once they hit their configured limit. Not admin-editable.

metadata.checkTextany

Text to check in the Twitter post, username, or bio.

metadata.requirePostLinkboolean

Flag indicating if the post link is required.

metadata.requirePostMediaLinkboolean

Flag indicating if media metadata is required.

metadata.preGeneratedPostTextstring

Pre-generated text template that will be used to prefill the post content.

metadata.rewardCriteria"IMPRESSIONS_COUNT" | "ELIGIBLE_POST"

Criteria to evaluate the reward.

Allowed values: "IMPRESSIONS_COUNT" | "ELIGIBLE_POST"
metadata.smartContractobject

Object containing details of the associated smart contract.

metadata.walletType"evm" | "solana" | "imx" | "sui" | "ton" | "cosmos" | "ultra" | "agw" | "flow_cadence" | "substrate"

Type of wallet associated with the rule.

Allowed values: "evm" | "solana" | "imx" | "sui" | "ton" | "cosmos" | "ultra" | "agw" | "flow_cadence" | "substrate"
metadata.imageUrlstring

URL of the image associated with the rule.

metadata.onlyRewardSingleTokenOwnershipboolean

give points for only one token ownership per contract

metadata.skipMultiplierboolean

Flag indicating if the multiplier is skipped.

metadata.completeProfileConditionsobject

Conditions for completing the profile.

metadata.steamAppIdstring

ID of the Steam app.

metadata.githubRepoUrlstring

URL of the GitHub repository to check for star.

metadata.githubBranchNamestring

Name of the GitHub branch to check for PR merge.

metadata.resetProgressOnClaimboolean

If enabled, the progress tracking row will be deleted after a successful claim, allowing the user to re-earn the rule.

metadata.rewardPerActionboolean

Flag indicating if the reward is rewarded per action.

metadata.rewardByBatchboolean

Flag indicating if the reward is rewarded by batch.

metadata.batchSizenumber

Number of tokens per batch.

metadata.youtubeVideoIdstring

ID of the Youtube video.

metadata.youtubeChannelIdstring

ID of the Youtube channel.

metadata.redditPostIdstring

ID of the Reddit post.

metadata.isRestrictedToNewUsersboolean

Flag indicating if the rule is restricted to new users.

metadata.allowMultipleRedemptionsboolean

Flag indicating if the rule allows multiple redemptions. Applies to Enter a Code only.

metadata.rewardBadgePerRangeboolean

Flag indicating if the rule can also reward badges per range.

metadata.swapobject

Metadata for swap loyalty rules

metadata.rewardPerValueboolean

Flag indicating if the rule should reward based on value of traded tokens instead of count.

metadata.conditionDescriptionstring

Description of the external rule condition (only for external rules)

metadata.directRpcboolean

Flag indicating if the rule should use direct RPC to get the balance of tokens.

metadata.erc20Type"erc20" | "native"

Type of ERC20 token for the loyalty rule.

Allowed values: "erc20" | "native"
metadata.rewardQualityPostsboolean

Flag indicating if the rule should reward quality posts.

metadata.minimumFollowerCountnumber

Minimum follower count for the rule. Accepts both number and string values.

metadata.autoCheckInRuleIdsarray<any>

Array of loyalty rule IDs that count as check-in when completed. If ["any"] then any rule completions count as check-in.

metadata.robinhoodSymbolsarray<string>
collectionAddressstring

Blockchain address of the associated collection

collectionsarray<object>

List of associated collections

collections.addressstringrequired

Blockchain address of the collection

collections.network"abstract" | "abstractTestnet" | "apechain" | "arbitrum" | "avalanche" | "avalancheFuji" | "base" | "baseSepolia" | "berachain" | "berachainArtio" | "berachainBepolia" | "binance" | "bscTestnet" | "campTestnet" | "fantom" | "fantomTestnet" | "flowMainnet" | "mainnet" | "nexus" | "nexusTestnet" | "optimism" | "polygon" | "polygon_mumbai" | "skaleNebula" | "skaleEuropa" | "skaleCalypso" | "solana" | "sophon" | "sophonTestnet" | "sui" | "superseed" | "superseedSepolia" | "vanar" | "xai" | "zksync" | "coti" | "cotiTestnet" | "dogeosTestnet" | "morph" | "morphTestnet" | "morphHolesky" | "ultra" | "ultraTestnet" | "nitrograph" | "sepolia" | "optimism_sepolia" | "arbitrumSepolia" | "goerli" | "optimism_goerli" | "arbitrumGoerli" | "basecamp" | "somnia" | "zkverify" | "polkadot" | "kusama" | "horizen" | "horizenTestnet" | "robinhoodChain" | "robinhoodChainTestnet" | "flow_cadence"required

Blockchain network for the collection

Allowed values: "abstract" | "abstractTestnet" | "apechain" | "arbitrum" | "avalanche" | "avalancheFuji" | "base" | "baseSepolia" | "berachain" | "berachainArtio" | "berachainBepolia" | "binance" | "bscTestnet" | "campTestnet" | "fantom" | "fantomTestnet" | "flowMainnet" | "mainnet" | "nexus" | "nexusTestnet" | "optimism" | "polygon" | "polygon_mumbai" | "skaleNebula" | "skaleEuropa" | "skaleCalypso" | "solana" | "sophon" | "sophonTestnet" | "sui" | "superseed" | "superseedSepolia" | "vanar" | "xai" | "zksync" | "coti" | "cotiTestnet" | "dogeosTestnet" | "morph" | "morphTestnet" | "morphHolesky" | "ultra" | "ultraTestnet" | "nitrograph" | "sepolia" | "optimism_sepolia" | "arbitrumSepolia" | "goerli" | "optimism_goerli" | "arbitrumGoerli" | "basecamp" | "somnia" | "zkverify" | "polkadot" | "kusama" | "horizen" | "horizenTestnet" | "robinhoodChain" | "robinhoodChainTestnet" | "flow_cadence"
collections.symbolstring

Symbol of the collection.

hideInUiboolean

Whether to hide this rule in the user interface

Default: false
trackProgressboolean

Flag indicating if the progress is tracked. If enabled, the rule can only be completed once the progress is 100%.

progressType"counter" | "percentage"

How tracked progress is interpreted. "percentage" counts 0-100 and is shown as a percentage. "counter" counts up to the highest reward range end and is shown as a raw count.

Allowed values: "counter" | "percentage"
showBeforeStartboolean

Whether to show this rule before the start time

Default: false
isRequiredboolean

Whether this rule is mandatory

Default: false
oauthCredentialsIdstring<uuid>

OAuth credentials associated with the rule

loyaltyCurrencyIdstring<uuid>

Unique identifier for the loyalty currency. Optional when rewardType is token and tokenReward is provided; backend will find or create the currency from the selected contract.

tokenRewardobject

When rewardType is token, provide relayer and either an ERC-20 contract or isNative=true to find or create loyalty currency and onchain token.

tokenReward.relayerIdstring<uuid>required

Stratus relayer for token distribution (same network as contract)

tokenReward.contractIdstring<uuid>

ERC-20 contract to reward with; must match relayer network. Required unless isNative is true.

tokenReward.isNativeboolean

When true, reward is the chain native gas token (ETH, MATIC, BNB, …) and contractId is omitted.

loyaltyRuleGroupIdany

Unique identifier for the loyalty rule group

rewardType"points" | "multiplier" | "badge" | "token"

Type of reward issued by the rule

Allowed values: "points" | "multiplier" | "badge" | "token"
Default: "points"
loyaltyBadgeIdstring<uuid>

Unique identifier for the loyalty badge

mediaUrlstring

URL of the media to be displayed

loyaltyUserAllotmentCsvUrlstring<uri>

URL for uploading loyalty user allotment via CSV

maxAmountPerIntervalnumber

The maximum amount of points a user can earn per interval. Available for the smart contract and external rules.

maxAmountInterval"daily" | "weekly" | "monthly" | "lifetime"

The interval for the max amount. Available for the smart contract and external rules.

Allowed values: "daily" | "weekly" | "monthly" | "lifetime"
shopifyStoreUrlstring

URL of the Shopify store

externalIntegrationIdstring<uuid>

ID of the external integration

duplicatedFromIdstring<uuid>
rewardLifetime"permanent" | "dynamic"

The lifetime of the reward

Allowed values: "permanent" | "dynamic"
claimType"manual" | "auto"

The type of claim for the reward

Allowed values: "manual" | "auto"
contractIdsarray<string>

The IDs of the contracts

dappDeployedWithin"daily" | "weekly" | "monthly"

Filter dApps by deployment age before ranking.

Allowed values: "daily" | "weekly" | "monthly"
dappDataWindow"daily" | "weekly" | "monthly"

Reward based on data usage within the last day, week, or month. Leave it empty for all time usage.

Allowed values: "daily" | "weekly" | "monthly"
isDappRuleboolean

Routes rule rewards to the dApp owner address (for substitution-type rules: external_rule, smart_contract_event, stratus_function) or marks the rule as a dApp-attribution rule (for the dapps_by_* family). Defaults to true at the API for the dapps_by_* family when omitted, false otherwise. Immutable after creation.

Response

application/json

200