# Gumroad Product & Price Monitor - Versions and Memberships (`maydit/gumroad-product-price-monitor`) Actor

Monitor public Gumroad product prices, pay-what-you-want minimums, membership tiers, availability and ratings. Get saved field changes with source links and clear coverage reports.

- **URL**: https://apify.com/maydit/gumroad-product-price-monitor.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 saved observations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Gumroad Product & Price Monitor

**Know when a watched digital product changes its price, versions, membership tiers or public ratings.** Paste a few Gumroad product URLs and receive one structured observation per product, ready for a spreadsheet, pricing dashboard or AI workflow.

Built for creator businesses, product researchers and agencies following a specific competitive set. Each row preserves the source URL, currency, pricing model and observation time. Turn on comparison to get changed fields and the previous saved observation instead of manually comparing product pages.

### Start with one product

```json
{
  "productUrls": ["https://chrisnotion.gumroad.com/l/notionbundle"],
  "maxResults": 1
}
```

Click **Start**, then open the **Dataset** for product records. The **Coverage and diagnostics** output explains what was reached. The **Readable run report** provides a compact result and any follow-up steps.

No Gumroad account, API key or proxy is required. Empty input uses this public sample. The sample belongs to its independent creator and can change over time.

### What makes the output useful

| Need | Recorded output |
| --- | --- |
| Compare fixed prices | Source `basePriceCents`, `currency`, model and compatible `basePriceDeltaCents` |
| Understand flexible pricing | PWYW minimum, suggested and default amounts as separate values |
| Follow product versions | All published options, extra amounts, resulting one-time prices and source quantity fields |
| Track membership offers | Tier-specific prices by billing frequency; a zero product base never becomes a claim that the membership is free |
| Monitor public response | Aggregate rating count, average and count delta; no individual reviewer collection |
| Audit changes | `comparisonStatus`, `changedFields`, `previous`, source link and observation timestamp |

One paid row contains the product and its nested options. There is no separate result charge for each tier or billing frequency.

### Three ready-to-run recipes

#### 1. Fixed price and product versions

```json
{"productUrls":["https://chrisnotion.gumroad.com/l/notionbundle"],"maxResults":1}
```

#### 2. Pay-what-you-want pricing

```json
{"productUrls":["https://uri23prod.gumroad.com/l/suqziy"],"maxResults":1}
```

#### 3. Membership tiers

```json
{"productUrls":["https://stipplestamps.gumroad.com/l/monthlysubscription"],"maxResults":1}
```

The third recipe shows why `basePriceCents` alone is insufficient for memberships: use `options[].recurringPrices[]` and its frequency. A tier name is creator-supplied text, not a billing guarantee.

### Keep a change watchlist

```json
{
  "productUrls": [
    "https://chrisnotion.gumroad.com/l/notionbundle",
    "https://uri23prod.gumroad.com/l/suqziy"
  ],
  "maxResults": 5,
  "comparePrevious": true,
  "onlyChanges": true,
  "snapshotName": "creator-pricing"
}
```

The first complete run establishes a baseline and emits `new` rows. Later runs emit changed products; an unchanged run can correctly save zero rows. The baseline belongs to the normalized URL selection and snapshot name. Use one active writer for that selection. Changing the URL set starts a separate comparison scope.

If a source fails, a selected product remains unread, the time budget expires or the spending limit is reached, the run does **not** advance its stored baseline. Useful rows can still be returned with a partial report. Missing products never automatically become removal or discontinuation claims.

### Input reference

| Field | Default | Purpose |
| --- | --- | --- |
| `productUrls` | Sample product | Up to 20 public `https://creator.gumroad.com/l/product` URLs |
| `maxResults` | 5 | Maximum saved products, 1–20 |
| `comparePrevious` | false | Compare against this selection's last complete saved baseline |
| `onlyChanges` | false | Enable comparison and skip unchanged rows |
| `snapshotName` | `default` | Independent history label, 1–80 letters, numbers, underscores or hyphens |
| `maxRunSeconds` | 90 | Shared 30–120 second collection budget |

Common campaign tracking parameters are removed. Checkout, discount, variant-selection and other functional query parameters are rejected, so every observation represents the same public product view. Custom storefront domains and marketplace discovery are outside this Actor's scope.

### Reading prices correctly

Amounts ending in `Cents` preserve Gumroad's integer source fields. The Actor does not exchange currencies or assume that all currencies use two decimal places. For a USD product, 500 cents means USD 5.00. Compare amounts only when currency and pricing model agree; the simple base-price delta is null for recurring products and memberships.

For a one-time version, `oneTimePriceCents` is the base amount plus that version's additional amount. For a membership, use that option's recurring price for the desired frequency. PWYW values distinguish a minimum from a suggestion. An unknown quantity is `null`, not unlimited stock. Public ratings and quantities are source-reported; they do not establish sales volume, revenue or profitability.

Source semantics: [Gumroad flexible pricing guide](https://gumroad.com/help/article/133-pay-what-you-want-pricing) and [membership guide](https://gumroad.com/help/article/82-membership-products).

### Output, API and integrations

Export Dataset rows as JSON or CSV. JSON preserves nested versions, tier prices and previous observations. The `SUMMARY` record lists source coverage, saved rows, failures and history status; `RUN_REPORT` is a self-contained HTML view of the same evidence. Neither creates a paid product row.

Use an Apify saved task with your watchlist, then add a schedule or an integration to your own spreadsheet, database or alert workflow. An AI agent can pass the same compact input through the [Apify API](https://docs.apify.com/api/v2) or [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). Filter for changed rows before generating a pricing alert, and include the original source URL.

Pricing is **$0.00005 per Actor start plus $0.003 per saved product observation ($3 per 1,000)**. The Actor's live Pricing tab is authoritative. Unchanged rows skipped by `onlyChanges` create no result event; platform usage may still apply under your plan. Configure a maximum charge in Run options for a bounded run.

### Scope and reliability

This Actor reads public product-page structured data and respects robots directives. It does not sign in, bypass restrictions, execute checkout, download purchased files or retrieve purchaser records, contact emails or seller analytics. It records product facts through an explicit field allowlist. Unsupported source shapes fail visibly rather than generating guessed prices.

A product page is an observation, not a guarantee of checkout availability or final taxes, fees, discounts or purchasing-power adjustments. Upstream pages can change or become unavailable. The bounded URL watchlist is deliberate: use this tool for repeated monitoring, not complete Gumroad catalog discovery.

Need another source or found a changed page? Open an Actor issue with the public URL, run ID and expected field. Do not include credentials. Explore related tools and workflow examples at [Mayd It Data Tools](https://mayd-it.com/data-tools/).

# Actor input Schema

## `productUrls` (type: `array`):

Up to 20 exact https://creator.gumroad.com/l/product URLs. Empty uses the sample product. Custom domains, checkout parameters and catalog discovery are not supported.

## `maxResults` (type: `integer`):

Maximum confirmed rows saved. Nested versions, tiers and group metadata are included in the row. If requested observations remain, history is preserved and SUMMARY reports partial coverage.

## `comparePrevious` (type: `boolean`):

Compare with the last complete successful observation under the same input selection and snapshot name. First comparison establishes a baseline.

## `onlyChanges` (type: `boolean`):

Enables comparison. Unchanged observations are skipped and incur no result event; an unchanged run may correctly produce zero rows.

## `snapshotName` (type: `string`):

Use 1-80 letters, numbers, underscores or hyphens. One active writer per watchlist and snapshot; new names create independent history.

## `maxRunSeconds` (type: `integer`):

Shared deadline for all source reads and output. Failed, partial or spending-limited runs do not advance comparison history.

## Actor input object example

```json
{
  "productUrls": [
    "https://chrisnotion.gumroad.com/l/notionbundle"
  ],
  "maxResults": 5,
  "comparePrevious": false,
  "onlyChanges": false,
  "snapshotName": "default",
  "maxRunSeconds": 90
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `report` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "productUrls": [
        "https://chrisnotion.gumroad.com/l/notionbundle"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/gumroad-product-price-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "productUrls": ["https://chrisnotion.gumroad.com/l/notionbundle"] }

# Run the Actor and wait for it to finish
run = client.actor("maydit/gumroad-product-price-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "productUrls": [
    "https://chrisnotion.gumroad.com/l/notionbundle"
  ]
}' |
apify call maydit/gumroad-product-price-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maydit/gumroad-product-price-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/P7qdQvPZRGV0G6H5H/builds/2SzCHBjibnf8Egye9/openapi.json
