ClawSkills logoClawSkills

Gumroad

Gumroad API integration with managed OAuth. Access products, sales, subscribers, licenses, and webhooks for your digital storefront. Use this skill when users w

Introduction

# 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

```bash # 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`:

```bash export MATON_API_KEY="YOUR_API_KEY" ```

### Getting Your API Key

1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key

## Connection Management

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

### List Connections

```bash 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

```bash 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

```bash 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

```bash 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:

```bash 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

```bash 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

```bash 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

```bash GET /gumroad/v2/products/{product_id} ```

#### Update Product

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

name=Updated%20Name&price=1000 ```

#### Enable/Disable Product

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

disabled=true ```

#### Delete Product

```bash 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

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

#### Get Offer Code

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

#### Create Offer Code

```bash 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

```bash 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

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

### Sales Operations

#### List Sales

```bash 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

```bash GET /gumroad/v2/sales/{sale_id} ```

### Subscriber Operations

#### List Subscribers

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

#### Get Subscriber

```bash 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

```bash 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

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

product_id={product_id}&license_key={license_key} ```

#### Disable License

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

product_id={product_id}&license_key={license_key} ```

#### Decrement License Uses

```bash 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

```bash 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

```bash DELETE /gumroad/v2/resource_subscriptions/{resource_subscription_id} ```

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

### Variant Categories

#### List Variant Categories

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

#### Get Variant Category

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

#### Create Variant Category

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

title=Size ```

#### Delete Variant Category

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

### Variants

#### List Variants

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

#### Create Variant

```bash 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

```bash 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

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

### Custom Fields

#### List Custom Fields

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

#### Create Custom Field

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

name=Company%20Name&required=true ```

#### Update Custom Field

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

required=false ```

#### Delete Custom Field

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

## Pagination

Gumroad uses page-based pagination for endpoints that return lists:

```bash 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

```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

```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)

```python 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:

```bash echo $MATON_API_KEY ```

2. Verify the API key is valid by listing connections:

```bash 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

- [Gumroad API Overview](https://gumroad.com/api) - [Create API Application](https://help.gumroad.com/article/280-create-application-api) - [License Keys Help](https://help.gumroad.com/article/76-license-keys) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[email protected])

More Products