Subscription
Time-based subscription token with recurring payment approvals and auto-deletion on expiry
Category: Token Types
Summary
Required standards: ["Subscriptions"]
validTokenIds: MUST be exactly one token ID [{ "start": "1", "end": "1" }]
Subscription faucet approval requirements:
fromListId: "Mint"
overridesFromOutgoingApprovals: true
coinTransfers: at least 1 entry, both override flags false
predeterminedBalances.incrementedBalances.durationFromTimestamp: MUST be non-zero (duration in ms)
allowOverrideTimestamp: MUST be true
incrementTokenIdsBy: "0", incrementOwnershipTimesBy: "0"
orderCalculationMethod: MUST have exactly ONE method true (default: useOverallNumTransfers)
Duration constants: monthly = "2592000000", annual = "31536000000", daily = "86400000"
CRITICAL: recurringOwnershipTimes MUST be all-zeros { startTime: "0", intervalLength: "0", chargePeriodLength: "0" } β chain enforces mutual exclusivity with durationFromTimestamp
Instructions
Subscription Collection Configuration
When creating a subscription collection, you MUST follow these EXACT requirements:
Required Structure
Standards: MUST include "Subscriptions"
"standards": ["Subscriptions"]
Invariants: MUST set noCustomOwnershipTimes to FALSE
Subscriptions use time-dependent ownership β this invariant MUST be false or subscriptions cannot function.
"invariants": { "noCustomOwnershipTimes": false, ... }
validTokenIds: MUST be exactly one token ID (per tier)
"validTokenIds": [{ "start": "1", "end": "1" }]
Subscription Faucet Approval Requirements:
fromListId: MUST be "Mint"
tokenIds: MUST be exactly 1 token: [{ "start": "1", "end": "1" }]
coinTransfers: MUST have at least 1 entry, NO override flags (both false)
predeterminedBalances.incrementedBalances:
durationFromTimestamp: MUST be non-zero (subscription duration in milliseconds)
allowOverrideTimestamp: MUST be true
incrementTokenIdsBy: "0"
incrementOwnershipTimesBy: "0"
orderCalculationMethod: MUST have EXACTLY ONE method set to true (default: useOverallNumTransfers)
overridesFromOutgoingApprovals: true (required for Mint approvals)
Duration Constants (in milliseconds)
Monthly: "2592000000" (30 days)
Annual: "31536000000" (365 days)
Daily: "86400000" (24 hours)
Complete Example
Subscription-Specific Gotchas
MUST have exactly 1 token ID (not multiple)
coinTransfers override flags MUST be false (not true)
durationFromTimestamp MUST be non-zero
allowOverrideTimestamp MUST be true
CRITICAL MUTUAL EXCLUSIVITY: The chain enforces that ONLY ONE of
durationFromTimestamp,incrementOwnershipTimesBy, orrecurringOwnershipTimescan be non-zero. For subscriptions, usedurationFromTimestampand keeprecurringOwnershipTimesas ALL ZEROS:{ "startTime": "0", "intervalLength": "0", "chargePeriodLength": "0" }. DO NOT set non-zero values inrecurringOwnershipTimesβ the template already has the correct structure.
Common Mistakes
DON'T set recurringOwnershipTimes to non-zero values β it is mutually exclusive with durationFromTimestamp. Keep all fields as "0".
DON'T forget durationFromTimestamp must be non-zero β this is the subscription duration in milliseconds (e.g. "2592000000" for 30 days).
DON'T forget allowOverrideTimestamp: true β subscriptions need this so each mint gets its own start timestamp.
DON'T use multiple token IDs β subscriptions must use exactly one token ID [{ "start": "1", "end": "1" }].
DON'T set coinTransfers override flags to true β for standard subscription payments, both overrideFromWithApproverAddress and overrideToWithInitiator must be false.
DON'T set noCustomOwnershipTimes: true in invariants β subscriptions require noCustomOwnershipTimes: false (or omit the invariant) because each subscription period mints a new ownershipTime window.
Last updated