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, verify licenses, view sales data, or set up webhook notifications. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key.

تثبيت
$clawhub install gumroad

Gumroad

Access the Gumroad API with managed OAuth authentication. Manage products, view sales, verify licenses, and set up webhooks for your digital storefront.

Quick Start

# 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

Base URL

https://gateway.maton.ai/gumroad/v2/{resource}

The gateway proxies requests to api.gumroad.com/v2 and automatically injects your OAuth token.

Authentication

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"

Getting Your API Key

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key

Connection Management

Manage your Gumroad OAuth connections at https://ctrl.maton.ai.

List Connections

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

Create Connection

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

Get Connection

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: json { "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.

Delete Connection

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

Specifying Connection

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.

API Reference

User Info

Get Current User

GET /gumroad/v2/user

Response: json { "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": "[email protected]", "display_name": "Chris" } }

Product Operations

List Products

GET /gumroad/v2/products

Response: json { "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 Product

GET /gumroad/v2/products/{product_id}

Update Product

PUT /gumroad/v2/products/{product_id}
Content-Type: application/x-www-form-urlencoded

name=Updated%20Name&price=1000

Enable/Disable Product

PUT /gumroad/v2/products/{product_id}/disable
Content-Type: application/x-www-form-urlencoded

disabled=true

Delete Product

DELETE /gumroad/v2/products/{product_id}

Note: Creating new products via API is not supported. Products must be created through the Gumroad website.

Offer Code Operations

List Offer Codes

GET /gumroad/v2/products/{product_id}/offer_codes

Get Offer Code

GET /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id}

Create Offer Code

POST /gumroad/v2/products/{product_id}/offer_codes
Content-Type: application/x-www-form-urlencoded

name=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)

Update Offer Code

PUT /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id}
Content-Type: application/x-www-form-urlencoded

max_purchase_count=100

Delete Offer Code

DELETE /gumroad/v2/products/{product_id}/offer_codes/{offer_code_id}

Sales Operations

List Sales

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 pagination

Example with filters: bash GET /gumroad/v2/sales?after=2026-01-01&before=2026-12-31

Response: json { "success": true, "sales": [ { "id": "sale_abc123", "email": "[email protected]", "seller_id": "seller123", "product_id": "prod123", "product_name": "My Product", "price": 500, "currency_symbol": "$", "created_at": "2026-01-15T10:30:00Z" } ] }

Get Sale

GET /gumroad/v2/sales/{sale_id}

Subscriber Operations

List Subscribers

GET /gumroad/v2/products/{product_id}/subscribers

Get Subscriber

GET /gumroad/v2/subscribers/{subscriber_id}

Response: json { "success": true, "subscriber": { "id": "sub123", "product_id": "prod123", "product_name": "Monthly Subscription", "user_id": "user123", "user_email": "[email protected]", "status": "alive", "created_at": "2026-01-01T00:00:00Z" } }

License Operations

Verify License

POST /gumroad/v2/licenses/verify
Content-Type: application/x-www-form-urlencoded

product_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): json { "success": true, "uses": 1, "purchase": { "seller_id": "seller123", "product_id": "prod123", "product_name": "My Product", "permalink": "abc", "email": "[email protected]", "license_key": "ABC-123-DEF", "quantity": 1, "created_at": "2026-01-15T00:00:00Z" } }

Response (failure): json { "success": false, "message": "That license does not exist for the provided product." }

Enable License

PUT /gumroad/v2/licenses/enable
Content-Type: application/x-www-form-urlencoded

product_id={product_id}&license_key={license_key}

Disable License

PUT /gumroad/v2/licenses/disable
Content-Type: application/x-www-form-urlencoded

product_id={product_id}&license_key={license_key}

Decrement License Uses

PUT /gumroad/v2/licenses/decrement_uses_count
Content-Type: application/x-www-form-urlencoded

product_id={product_id}&license_key={license_key}

Resource Subscriptions (Webhooks)

Subscribe to notifications for sales and other events.

List Resource Subscriptions

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_restarted

Response: json { "success": true, "resource_subscriptions": [ { "id": "wX43hzi-s7W4JfYFkxyeiQ==", "resource_name": "sale", "post_url": "https://example.com/webhook" } ] }

Delete Resource Subscription

DELETE /gumroad/v2/resource_subscriptions/{resource_subscription_id}

Response: json { "success": true, "message": "The resource_subscription was deleted successfully." }

Variant Categories

List Variant Categories

GET /gumroad/v2/products/{product_id}/variant_categories

Get Variant Category

GET /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}

Create Variant Category

POST /gumroad/v2/products/{product_id}/variant_categories
Content-Type: application/x-www-form-urlencoded

title=Size

Delete Variant Category

DELETE /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}

Variants

List Variants

GET /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants

Create Variant

POST /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants
Content-Type: application/x-www-form-urlencoded

name=Large&price_difference=200

Update Variant

PUT /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants/{variant_id}
Content-Type: application/x-www-form-urlencoded

name=Extra%20Large

Delete Variant

DELETE /gumroad/v2/products/{product_id}/variant_categories/{variant_category_id}/variants/{variant_id}

Custom Fields

List Custom Fields

GET /gumroad/v2/products/{product_id}/custom_fields

Create Custom Field

POST /gumroad/v2/products/{product_id}/custom_fields
Content-Type: application/x-www-form-urlencoded

name=Company%20Name&required=true

Update Custom Field

PUT /gumroad/v2/products/{product_id}/custom_fields/{name}
Content-Type: application/x-www-form-urlencoded

required=false

Delete Custom Field

DELETE /gumroad/v2/products/{product_id}/custom_fields/{name}

Pagination

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.

Code Examples

JavaScript

const response = await fetch(
  'https://gateway.maton.ai/gumroad/v2/products',
  {
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`
    }
  }
);
const data = await response.json();

Python

import os
import requests

response = requests.get(
    'https://gateway.maton.ai/gumroad/v2/products',
    headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()

Python (Verify License)

import os
import requests

response = 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']}")

Notes

  • All responses include a success boolean field
  • Product creation is not available via API - products must be created through the Gumroad website
  • POST/PUT requests use application/x-www-form-urlencoded content type (not JSON)
  • Prices are in cents (e.g., 500 = $5.00)
  • License keys are case-insensitive
  • Resource subscription webhooks send POST requests to your specified URL
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments

Error Handling

Status Meaning
400 Missing Gumroad connection or bad request
401 Invalid or missing Maton API key
404 Resource not found (returned with success: false)
429 Rate limited
4xx/5xx Passthrough error from Gumroad API

Gumroad errors typically return HTTP 404 with a JSON body: json { "success": false, "message": "Error description" }

Troubleshooting: API Key Issues

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
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

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with gumroad. For example:
  • Correct: https://gateway.maton.ai/gumroad/v2/user
  • Incorrect: https://gateway.maton.ai/v2/user

Resources