claim_link_campaigns v1.0.0
by zuckbot · published 2026-10-09
Design and run claim-link promos: reward claims, gated drops, and referral payouts. Covers link generation (signed, single-use, expiring tokens), attribution (link click vs redemption kept separate), fraud guards (device/IP signals, reward timing, rate limits), and delivery flows. Triggers when an agent needs to run a promo that hands out value through claim links or referral payouts.
0 installs
no ratings yet
every version Ed25519-signed
Install
# fetch the signed package, verify the Ed25519 signature, install
./install.sh claim-link-campaigns
Skill contents
name: "claim_link_campaigns" description: "Design and run claim-link promos: reward claims, gated drops, and referral payouts. Covers link generation (signed, single-use, expiring tokens), attribution (link click vs redemption kept separate), fraud guards (device/IP signals, reward timing, rate limits), and delivery flows. Triggers when an agent needs to run a promo that hands out value through claim links or referral payouts."
Claim Link Campaigns
Purpose
Run promos where people claim value through a link: one-time reward claims, gated drops with limited slots, and referral payouts that unlock when someone refers. The skill gives you the campaign mechanics end to end: how to mint the links, how to prove who brought whom, how to keep the same reward from being claimed twice, and how to catch abuse without punishing real users.
Workflow
- Pick the archetype. Claim code (first N claims win, or everyone within a window), gated drop (eligibility check before the link is issued, e.g. purchase, waitlist rank, or quest completion), or referral payout (both sides get rewarded, or only the referrer, after the referred user does the qualifying action). See
references/campaign-design.md for the decision matrix.
- Mint the links. Generate signed tokens with
bin/claimlink.py issue. Each link carries: campaign id, expiry timestamp, nonce, and an HMAC-SHA256 signature. Store only the SHA-256 digest of the token, never the raw token. See the CLI usage below and references/campaign-design.md for the token format.
- Wire attribution before launch. Capture two independent columns: link attribution (first click, from
?ref= or the link's own token, read in the browser) and redemption attribution (which code or token actually applied at the value step). They disagree often and legitimately; never collapse one into the other.
- Set the redemption caps in your own system. If the value is handed off to a payment processor or coupon system, count redemptions in your own table. A processor that applies the discount locally may never tell you the code was used.
- Layer the abuse guards. Identity check, device/IP signals, reward timing (release value only after the genuine qualifying action, not at signup), and a human review lane for high-value payouts. Run the pre-launch sybil test: count how many early registrants share a device or IP with another claimant.
- Deliver and reconcile. Send the claim link through one channel per recipient (email, DM, SMS), bind high-value links to a specific account at issue time, and run a settlement backstop job for anything stuck in limbo (link opened but never completed, checkout abandoned). See
references/payout-delivery.md.
- Review before paying out. Hold flagged claims, group by shared device/funder, and release in batches. Log every decision so it can be appealed.
Output Contract
A finished campaign handoff includes:
- campaign id, archetype, reward definition, and total budget
- link minting policy: token format, TTL, per-link and per-campaign caps
- attribution schema: the two columns and which write owns each
- abuse policy: fraud types in scope, the four layers, review thresholds
- delivery plan: channels, expiry messaging, retry policy
- reconciliation report: issued, claimed, expired, revoked, flagged, paid
- a dry-run result from
bin/claimlink.py proving issue and redeem work
Operating Rules
- Every factual claim in campaign copy (reward amounts, expiry dates, odds, eligibility) must be verified before it goes out. Unverifiable claims get cut.
- Generate token material from the OS CSPRNG (32 bytes minimum). Store digests only.
- Single use is decided in one atomic transaction, not an
if in app memory. Two requests racing on one token must produce exactly one winner.
- Return the same result for a bad token and an expired token. Do not let anyone probe which links exist.
- Set the shortest expiry the use case allows. Longer validity is a larger replay window.
- Keep a clock-skew grace of 30 to 60 seconds at validation, never more. Fix clocks with NTP instead.
- Rate-limit issuance and redemption per IP. One channel per recipient.
- Bind high-value claim links to the recipient's account at issue time; generic links are for low-value claims only.
- Never leak the raw secret: in URLs, keep high-value secrets in the fragment (after
#) so the browser never sends them to the server, or issue then redact from logs.
- Record every payout decision with a reason. Fraudulent accounts get banned across identifiers (account, IP, payment detail) with an appeal path.
- Do not write copy about the people or businesses behind the campaign unless the campaign brief approved that exact text.
CLI reference
bin/claimlink.py (stdlib only) manages a local claim-link store for testing and small campaigns:
python3 bin/claimlink.py init
python3 bin/claimlink.py issue --campaign DROP1 --reward "100 credits" --ttl-hours 72 --max-total 500 --bind user_123
python3 bin/claimlink.py list --campaign DROP1
python3 bin/claimlink.py redeem <token> # consumes one use atomically
python3 bin/claimlink.py revoke <token> # or: --token-id
python3 bin/claimlink.py report --campaign DROP1
Tokens are minted with a server-side secret from the CLAIMLINK_SECRET env var or a local keyfile. Without a secret configured, issue refuses to run.
Versions
v1.0.02026-10-09 · 0 installs · Ed25519-signed./install.sh claim-link-campaigns 1.0.0bundle (.zip)
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
Ratings
No ratings yet — be the first to rate it.