Referral abuse
Check referral and promo attribution before issuing a bonus.
Verify attribution
Send the referrer's existing account ID alongside the new account. Resolve attribution on your backend; do not trust an unvalidated browser claim. The referrer ID must be a nonblank string of at most 256 characters.
POST /v1/verify
{ "secret": "sk_…", "token": "…", "account": { "id": "new-account", "email": "person@example.com" },
"referrer": { "accountId": "existing-account" } }
{ "success": true, "decision": "limit", "score": 0,
"referral": { "selfReferral": true, "ring": false }, "grant": { "share": 0.1, "credits": null, "requires": null }, "ref": "ev_…", "…": "…" }The grant follows your site's trial policy; the example share is illustrative. Referral results accompany attributed successful verifies with an account. No account means no referral edge or referral result. Public test keys keep their fixed, storage-free behaviour.
Signals
| Reason | Weight | Link |
|---|---|---|
self_referral | 60 | Same account, a shared visitor/fingerprint key from the referrer's last verify, normalized email seen within 30 days, or the same network prefix within 24 hours. Diagnostic detail lists account,device,email,network as applicable. |
referral_ring | 50 | More than five distinct referred accounts in 30 days each share a device with another account referred by the same referrer. Re-verifying one account does not increase the count. |
Both reasons have scored: false: they flag abuse without increasing the bot score. Human referral abuse yields limit in block mode, using the normal grant policy. Observe mode returns allow with wouldDecide: limit and wouldGrant. Customer rules still apply. Reason details remain owner-only diagnostics; the referral booleans are public API fields.
Bonus policy
Do not pay the referral bonus when decision != "allow" or referral.selfReferral. For ring flags in observe mode, inspect referral.ring or wouldDecide before paying. Verification success validates the token; it says nothing about bonus eligibility.
const bonusEligible = result.success && result.decision === 'allow'
&& !result.referral?.selfReferral && !result.referral?.ring;Storage and availability
Referral edges contain only site-scoped keyed account/device hashes, link kinds, flags and timestamps. No raw account IDs, emails, IPs or user agents are added. Edges expire after 30 days through scheduled cleanup. A storage outage or pending migration does not reject an otherwise valid token; correlation may be unavailable. A false referral flag is not proof of independence. Account clusters and /v1/cluster are unchanged.