Gumroad
Gumroad API integration with managed OAuth. Access products, sales, subscribers, licenses, and webhooks for your digital storefront. Use this skill when users want to manage their Gumroad products, ve
Gumroad API integration with managed OAuth. Access products, sales, subscribers, licenses, and webhooks for your digital storefront. Use this skill when users want to manage their Gumroad products, ve
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
Access the Gumroad API with managed OAuth authentication. Manage products, view sales, verify licenses, and set up webhooks for your digital storefront.
# Get current user info python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/gumroad/v2/user') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
https://gateway.maton.ai/gumroad/v2/{resource}
The gateway proxies requests to
api.gumroad.com/v2 and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as
MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Gumroad OAuth connections at
https://ctrl.maton.ai.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=gumroad&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'gumroad'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Response:
{ "connection": { "connection_id": "e1a4444f-2bb8-4e09-9265-3afe71b74b1f", "status": "ACTIVE", "creation_time": "2026-02-08T06:22:48.654579Z", "last_updated_time": "2026-02-08T06:23:07.420381Z", "url": "https://connect.maton.ai/?session_token=...", "app": "gumroad", "metadata": {} } }
Open the returned
url in a browser to complete OAuth authorization.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If you have multiple Gumroad connections, specify which one to use with the
Maton-Connection header:
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/gumroad/v2/products') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', 'e1a4444f-2bb8-4e09-9265-3afe71b74b1f') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
GET /gumroad/v2/user
Response:
{ "success": true, "user": { "name": "Chris", "currency_type": "usd", "bio": null, "twitter_handle": null, "id": "1690942847664", "user_id": "QmTtTnViFSoocHAexgLuJw==", "url": "https://chriswave1246.gumroad.com", "profile_url": "https://public-files.gumroad.com/...", "email": "chris@example.com", "display_name": "Chris" } }
GET /gumroad/v2/products
Response:
{ "success": true, "products": [ { "id": "ABC123", "name": "My Product", "price": 500, "currency": "usd", "short_url": "https://gumroad.com/l/abc", "sales_count": 10, "sales_usd_cents": 5000 } ] }
GET /gumroad/v2/products/{product_id}
PUT /gumroad/v2/products/{product_id} Content-Type: application/x-www-form-urlencodedname=Updated%20Name&price=1000
PUT /gumroad/v2/products/{product_id}/disable Content-Type: application/x-www-form-urlencodeddisabled=true
DELETE /gumroad/v2/products/{product_id}
Note: Creating new products via API is not supported. Products must be created through the Gumroad website.
GET /gumroad/v2/products/{product_id}/offer_codes
GET /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id}
POST /gumroad/v2/products/{product_id}/offer_codes Content-Type: application/x-www-form-urlencodedname=SUMMER20&amount_off=20
Parameters:
name - The code customers enter (required)amount_off - Cents or percentage off (required)offer_type - "cents" or "percent" (default: "cents")max_purchase_count - Maximum uses (optional)PUT /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id} Content-Type: application/x-www-form-urlencodedmax_purchase_count=100
DELETE /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id}
GET /gumroad/v2/sales
Query parameters:
after - Only sales after this date (YYYY-MM-DD)before - Only sales before this date (YYYY-MM-DD)page - Page number for paginationExample with filters:
GET /gumroad/v2/sales?after=2026-01-01&before=2026-12-31
Response:
{ "success": true, "sales": [ { "id": "sale_abc123", "email": "customer@example.com", "seller_id": "seller123", "product_id": "prod123", "product_name": "My Product", "price": 500, "currency_symbol": "$", "created_at": "2026-01-15T10:30:00Z" } ] }
GET /gumroad/v2/sales/{sale_id}
GET /gumroad/v2/products/{product_id}/subscribers
GET /gumroad/v2/subscribers/{subscriber_id}
Response:
{ "success": true, "subscriber": { "id": "sub123", "product_id": "prod123", "product_name": "Monthly Subscription", "user_id": "user123", "user_email": "subscriber@example.com", "status": "alive", "created_at": "2026-01-01T00:00:00Z" } }
POST /gumroad/v2/licenses/verify Content-Type: application/x-www-form-urlencodedproduct_id={product_id}&license_key={license_key}
Parameters:
product_id - The product ID (required)license_key - The license key to verify (required)increment_uses_count - Increment the use count (default: true)Response (success):
{ "success": true, "uses": 1, "purchase": { "seller_id": "seller123", "product_id": "prod123", "product_name": "My Product", "permalink": "abc", "email": "customer@example.com", "license_key": "ABC-123-DEF", "quantity": 1, "created_at": "2026-01-15T00:00:00Z" } }
Response (failure):
{ "success": false, "message": "That license does not exist for the provided product." }
PUT /gumroad/v2/licenses/enable Content-Type: application/x-www-form-urlencodedproduct_id={product_id}&license_key={license_key}
PUT /gumroad/v2/licenses/disable Content-Type: application/x-www-form-urlencodedproduct_id={product_id}&license_key={license_key}
PUT /gumroad/v2/licenses/decrement_uses_count Content-Type: application/x-www-form-urlencodedproduct_id={product_id}&license_key={license_key}
Subscribe to notifications for sales and other events.
GET /gumroad/v2/resource_subscriptions?resource_name=sale
Parameters:
resource_name - Required. One of: sale, refund, dispute, dispute_won, cancellation, subscription_updated, subscription_ended, subscription_restartedResponse:
{ "success": true, "resource_subscriptions": [ { "id": "wX43hzi-s7W4JfYFkxyeiQ==", "resource_name": "sale", "post_url": "https://example.com/webhook" } ] }
DELETE /gumroad/v2/resource_subscriptions/{resource_subscription_id}
Response:
{ "success": true, "message": "The resource_subscription was deleted successfully." }
GET /gumroad/v2/products/{product_id}/variant_categories
GET /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}
POST /gumroad/v2/products/{product_id}/variant_categories Content-Type: application/x-www-form-urlencodedtitle=Size
DELETE /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}
GET /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants
POST /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants Content-Type: application/x-www-form-urlencodedname=Large&price_difference=200
PUT /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants/{variant_id} Content-Type: application/x-www-form-urlencodedname=Extra%20Large
DELETE /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants/{variant_id}
GET /gumroad/v2/products/{product_id}/custom_fields
POST /gumroad/v2/products/{product_id}/custom_fields Content-Type: application/x-www-form-urlencodedname=Company%20Name&required=true
PUT /gumroad/v2/products/{product_id}/custom_fields/{name} Content-Type: application/x-www-form-urlencodedrequired=false
DELETE /gumroad/v2/products/{product_id}/custom_fields/{name}
Gumroad uses page-based pagination for endpoints that return lists:
GET /gumroad/v2/sales?page=1 GET /gumroad/v2/sales?page=2
Continue incrementing the page number until you receive an empty list.
const response = await fetch( 'https://gateway.maton.ai/gumroad/v2/products', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json();
import os import requestsresponse = requests.get( 'https://gateway.maton.ai/gumroad/v2/products', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} ) data = response.json()
import os import requestsresponse = requests.post( 'https://gateway.maton.ai/gumroad/v2/licenses/verify', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, data={ 'product_id': 'your_product_id', 'license_key': 'CUSTOMER-LICENSE-KEY' } ) result = response.json() if result['success']: print(f"License valid! Uses: {result['uses']}") else: print(f"Invalid: {result['message']}")
success boolean fieldapplication/x-www-form-urlencoded content type (not JSON)jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| 400 | Missing Gumroad connection or bad request |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found (returned with ) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Gumroad API |
Gumroad errors typically return HTTP 404 with a JSON body:
{ "success": false, "message": "Error description" }
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
gumroad. For example:https://gateway.maton.ai/gumroad/v2/userhttps://gateway.maton.ai/v2/userNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.