{
  "id": 15692511,
  "title": "Your Gumroad license check probably lets refunded buyers in (and how to fix it)",
  "url": "https://urgent.news/2026/10/20/your-gumroad-license-check-probably-lets-refunded-buyers-in-and-how",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-20T03:35:45.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/pau_drudis_6182de07fdc9f0/your-gumroad-license-check-probably-lets-refunded-buyers-in-and-how-to-fix-it-368g"
  },
  "original_language": "en",
  "account": "If you sell software on Gumroad and restrict it with license keys, there is a possibility that your verification process may allow refunded buyers to continue using your application. The current verification code checks if the key exists by looking for a success response from Gumroad's API. However, after a buyer refunds, disputes, or cancels a subscription, the verify endpoint still returns a success status of true.\n\nTo fix this issue, you need to check not only the success flag but also the purchase flags. The evaluation function first checks if the verification was successful. If not, it returns an invalid license error. Then, it checks the purchase object for flags such as refunded, chargebacked, disputed, subscription ended, or subscription failed. If any of these flags are true, it returns an error with the corresponding reason. Otherwise, it returns a valid status.\n\nA couple of additional tips are to send increment_uses_count=false on re-checks and to only increment the uses count on the first activation. Re-check the verification periodically, as refunds occur after activation and may not be immediately visible. Cache the last good result to prevent the app from breaking offline. The provided code is available in an MIT repository for free use.",
  "summary": "If you sell software on Gumroad and gate it with license keys, there's a good chance your check looks like this: const res = await fetch ( \" https://api.gumroad.com/v2/licenses/verify \" , { method : \" POST \" , body : new URLSearchParams ({ product_id , license_key }), }). then (( r ) => r . json ()); if ( res . success ) unlock (); // looks fine... The problem: success only tells you the key…",
  "key_points": [
    "Gumroad license check may allow refunded buyers to use software",
    "Verify endpoint returns true status even after refunds or cancellations"
  ],
  "editors_take": "Updating license verification logic to include purchase flags prevents refunded or disputed customers from maintaining unauthorized access to software sold through the Gumroad platform.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}