> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pocketsflow.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Limited drops, PDF stamping & download limits

> Sell a fixed number of copies, stamp PDFs with the buyer's email and limit downloads with your API key or the MCP server.

Three settings that live on a product. **Limited drops** and **PDF
stamping** need the **Starter** plan (or higher) to turn on; **download
limits** need **Growth**. Reading them and turning them off is never gated. A
call that turns one on below its plan answers `403` with
`code: "FEATURE_LOCKED"`:

```json theme={"system"}
{
  "error": "FEATURE_LOCKED",
  "code": "FEATURE_LOCKED",
  "upgradeRequired": true,
  "message": "This feature is part of a higher plan. Please upgrade your plan to use it.",
  "details": { "feature": "downloadLimits", "requiredPlan": "tier2", "requiredPlanName": "Growth" }
}
```

## Limited drops

| Method | Path | MCP tool |
| - | - | - |
| `GET` | `/products/{id}/limited-drop` | `get_limited_drop` |
| `PATCH` | `/products/{id}/limited-drop` | `update_limited_drop` |
| `GET` | `/products/{id}/drop` (public) | `get_limited_drop_availability` |

```bash theme={"system"}
curl -X PATCH https://api.pocketsflow.com/products/665f1c2a9b3e4a0012ab34cd/limited-drop \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "quantity": 100, "restockOnRefund": false }'
```

```json theme={"system"}
{
  "limitedDrop": {
    "enabled": true,
    "quantity": 100,
    "restockOnRefund": false,
    "sold": 0,
    "reserved": 0,
    "remaining": 100,
    "soldOut": false,
    "startedAt": "2026-10-16T09:00:00.000Z"
  }
}
```

| Field | Type | Notes |
| - | - | - |
| `enabled` | boolean | Needs a `quantity` (in the body or saved). |
| `quantity` | integer | 1–1,000,000. Raising it reopens sales; lowering it under `sold` closes them. |
| `restockOnRefund` | boolean | A refunded order's copy goes back on sale (once). |
| `sold`, `reserved`, `remaining`, `soldOut` | read-only | `reserved` = copies held by buyers on the checkout right now. |

How the count stays exact:

* A buyer who opens the checkout **holds one copy for 15 minutes** (one per
  browser, so reloading or changing the order never takes a second copy). The
  hold is taken with a single atomic update that only succeeds while
  `sold + reserved < quantity`, so two buyers can never get the last copy.
* When the payment goes through, the hold becomes a sold copy. A declined
  card keeps the hold 5 more minutes (to try another card), then it goes
  back. Expired holds go back within a minute.
* No copy left: creating a checkout (and `POST /products/buy-free` for a free
  product) answers `409`:

```json theme={"system"}
{ "code": "SOLD_OUT", "reason": "sold_out", "message": "Sold out. Every copy of this product has been sold." }
```

`reason` is `all_reserved` while the last copies sit in other buyers'
checkouts ("check back in a few minutes"). A buyer who already paid is never
refused, even if their hold ran out.

`GET /products/{id}/drop` needs no API key — use it to show "35 of 100 left"
on your own site:

```json theme={"system"}
{ "enabled": true, "quantity": 100, "remaining": 35, "sold": 63, "reserved": 2, "soldOut": false }
```

If your plan no longer includes limited drops, the counter disappears and
the limit stops applying (sales are never blocked); your settings and counts
are kept.

## PDF stamping

| Method | Path | MCP tool |
| - | - | - |
| `GET` | `/products/{id}/pdf-stamping` | `get_pdf_stamping` |
| `PATCH` | `/products/{id}/pdf-stamping` | `update_pdf_stamping` |

```bash theme={"system"}
curl -X PATCH https://api.pocketsflow.com/products/665f1c2a9b3e4a0012ab34cd/pdf-stamping \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
```

When on, every PDF of the product is stamped as the buyer downloads it: a
small grey footer on each page, `Licensed to ada@example.com · Order
12CD56EF · Oct 16, 2026`, plus the same line in the file's metadata. A gift
is stamped with the recipient's email. Other files are delivered untouched,
and a PDF that can't be stamped (encrypted, damaged) is delivered as is.

## Download limits

| Method | Path | MCP tool |
| - | - | - |
| `GET` | `/products/{id}/download-limits` | `get_download_limits` |
| `PATCH` | `/products/{id}/download-limits` | `update_download_limits` |
| `GET` | `/orders/{id}/downloads` | `get_order_downloads` |
| `POST` | `/orders/{id}/downloads/reset` | `reset_order_downloads` |

```bash theme={"system"}
curl -X PATCH https://api.pocketsflow.com/products/665f1c2a9b3e4a0012ab34cd/download-limits \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "maxDownloads": 5, "expiryDays": 7 }'
```

| Field | Type | Notes |
| - | - | - |
| `maxDownloads` | integer \| null | Downloads per file per order, 1–1000. `null` = no count limit. |
| `expiryDays` | integer \| null | Days the links work after the purchase (or after you reset the buyer's downloads), 1–3650. `null` = never expire. |
| `applyToExisting` | boolean | Default `false`: only orders placed after you turned the limits on are limited. |
| `appliesFrom` | read-only | When the limits were last turned on. |

A browser retrying the same file within 30 seconds is not charged twice, and
resumed downloads never count. When a buyer runs out, their delivery page
shows how to contact you; `POST /orders/{id}/downloads/reset` gives them
everything back and restarts the expiry window:

```json theme={"system"}
{
  "downloads": {
    "limited": true,
    "maxDownloads": 5,
    "expiresAt": "2026-10-23T09:12:00.000Z",
    "expired": false,
    "remaining": 5,
    "exhausted": false,
    "files": [{ "key": "main", "name": "Field Guide", "used": 0, "remaining": 5 }],
    "stamped": true,
    "totalDownloads": 2,
    "lastDownloadAt": "2026-10-16T10:02:00.000Z",
    "resetAt": "2026-10-16T11:00:00.000Z",
    "resetCount": 1
  }
}
```

Resetting is never gated by plan. If your plan no longer includes download
limits, buyers download without limits again; your settings are kept.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.