Skip to main content
AC
Sales & RevOps4.9 KBMIT licensed

gumroad-api

Original, written for TechTide client work

Manage Gumroad products, sales, offer codes, licenses, subscribers, variants, and webhooks through the REST API v2. Use when checking sales data, creating discount codes, toggling or updating products, verifying license keys, pulling subscriber lists, or wiring sale webhooks. Not for creating new products or any browser-only flow: the API cannot create products, use gumroad-browser for that.

  • gumroad
  • api

SKILL.md

Gumroad API Management

The Gumroad API v2 handles everything after a product exists: sales pulls, discounts, licenses, subscribers, webhooks. It cannot create products. Product creation goes through gumroad-browser, always.

Basics

  • Base URL: https://api.gumroad.com/v2/. All responses are JSON with a success boolean.
  • Auth: an access token generated under Settings > Advanced in the Gumroad dashboard. Pass it as ?access_token=<GUMROAD_ACCESS_TOKEN>, a POST body field, or an Authorization: Bearer header.
  • Writes use Content-Type: application/x-www-form-urlencoded, not JSON bodies.
  • All money values are integer cents. price=4900 is $49.00.

Store the token in an env variable. Never commit it or echo it into logs.

Operation routing

Read references/endpoints.md when you need exact parameters, field lists, webhook payload shape, or MCP server setup. Route by task:

TaskMethod and path
List products / get product IDsGET /products
Update product fields, price, publish statePUT /products/:id
Enable or disable a productPUT /products/:id/enable or /disable
Pull sales, filter by dateGET /sales?after=<ISO>&before=<ISO>
Create or manage discount codesPOST/PUT/DELETE /products/:id/offer_codes
Variants and tiers/products/:id/variant_categories/...
Checkout custom fields/products/:id/custom_fields
Verify, enable, disable licensesPOST /licenses/verify, PUT /licenses/enable etc.
Subscriber listsGET /products/:id/subscribers
Webhooks (resource subscriptions)POST /resource_subscriptions
Authenticated account infoGET /user

Standard workflows

Monthly sales pull:

curl "https://api.gumroad.com/v2/sales?access_token=$GUMROAD_ACCESS_TOKEN&after=<MONTH_START>&before=<MONTH_END>"

Launch discount across products: GET /products for IDs, then per product:

curl -X POST "https://api.gumroad.com/v2/products/<PRODUCT_ID>/offer_codes" \
  -d "access_token=$GUMROAD_ACCESS_TOKEN" \
  -d "name=<CODE>" -d "amount_off=20" -d "offer_type=percent" -d "max_purchase_count=50"

Sale webhook to an automation endpoint:

curl -X POST "https://api.gumroad.com/v2/resource_subscriptions" \
  -d "access_token=$GUMROAD_ACCESS_TOKEN" \
  -d "resource_name=sale" -d "post_url=<WEBHOOK_URL>"

Error handling

  • 401: invalid or missing token. 404: resource not found. 422: invalid parameters. 429: rate limited, back off and retry.
  • Every error body carries success: false and a message. Check success on 200s too; some failures return 200 with success: false.
  • Paginate GET /sales with the page parameter for any range that might exceed one page.

Good vs bad

Good discount setup: create the code with max_purchase_count set, then GET it back and confirm amount_off, offer_type, and the cap before announcing the code anywhere.

Bad: fire the POST, see HTTP 200, and post the code publicly. offer_type defaulted wrong or the body was ignored, and a 20 percent code just became 20 cents off, or the cap is unlimited. The announcement makes the mistake irreversible.

Verification

Do this: after any write (product update, offer code, webhook, license change), GET the same resource back and compare every field you set. Expect the response to show success: true and the exact values sent. If a field differs or the GET 404s, the write did not take: fix the request before reporting the operation done.

Completion checklist

  • [ ] Token sourced from env, never hardcoded or logged
  • [ ] Every write verified with a read-back
  • [ ] Money values handled as integer cents
  • [ ] Date-filtered pulls checked for pagination
  • [ ] Anything needing product creation routed to gumroad-browser

Any box unchecked: not done. Fix or say so.

Footguns

  • Trying to create a product via the API: no such endpoint exists. Route to gumroad-browser instead of improvising with PUT.
  • amount_off is unit-ambiguous: cents when offer_type=cents, a percentage when offer_type=percent. Always send both fields together and verify with a read-back.
  • Sending JSON bodies: the API expects form encoding. JSON payloads fail or silently ignore fields.
  • Trusting HTTP 200: check the success field in the body. 200 with success: false is a failure.
  • Webhook endpoints receive buyer emails and order data: point post_url only at endpoints you control over HTTPS, and treat the payload as PII.

Reference files

More in Sales & RevOps

All skills