Create a sellable drop from vault items
API reference

Create a sellable drop from vault items

Packages up to 10 vault items into a drop and returns a checkout URL.

View as MarkdownUpdated Aug 19, 2026
POST/api/external/v1/dropsalso served at /api/external/drops

Packages up to 10 vault items into a drop and returns a checkout URL.

Price is USD dollars: either 0 (free) or between $5 and $750. Use APPROVED vault items — the drop inherits its moderation status from its media, so a drop built from approved items is sellable (and attachable to a post) immediately, while one containing PENDING items waits for review. Hand the buyer the returned buyUrl, or build a Telegram link from GET /api/external/v1/links' telegram.buyTemplate.

One drop, many fans. Don't create a copy per recipient. Create the drop once and give each fan their own link with a reference: buyUrl?m={yourRef} on the web, or startapp=b_{productId}_{yourRef} in Telegram. The reference comes back on every paid order — see Broadcast one drop to many fans. Different prices still need separate drops.

`description` is validated but NOT stored

The description field runs through the prohibited-word filter and is then deliberately discarded — it is never shown anywhere on Dropfans. You get a 200 with no indication it was dropped. Treat it as a moderation input only.

Authentication

Send the creator's API key as a bearer token: Authorization: Bearer dpfn_…. See Authentication & API keys.

For a creator you manage or onboarded

POST /api/external/v1/creators/{creatorId}/drops — an agency's own key for a creator or AI persona it manages (needs canManageDrops), or your app owner's own key for an account your app onboarded. The X-Dropfans-Account header still works but is deprecated. See Acting for a creator.

Request body

Content type: application/json

NameTypeRequiredDescription
namestringOptionalDrop title, shown at checkout. Falsy values are stored as null.
descriptionstringOptionalChecked for prohibited words, then discarded — never persisted or displayed.
pricenumberRequiredUSD dollars. 0 = free; otherwise $5–$750.
Min: 0
Max: 750
allowDownloadbooleanOptionalImages only: when true, buyers get a Download button serving a watermarked, metadata-stripped JPEG. Videos always stream behind DRM and are never downloadable. Off unless explicitly set.
Default: false
vaultItemIdsstring[]Required1–10 vault item ids, in display order. The first becomes the cover.
Max items: 10
A $25 three-item drop
{
  "name": "Beach set — 6 photos",
  "price": 25,
  "vaultItemIds": [
    "clxv1a2b30001item",
    "clxv1a2b30002item",
    "clxv1a2b30003item"
  ]
}

Responses

200Created. Keep the productId — sales polling, previews and post attachment all key on it.
NameTypeDescription
productIdstringThe new drop’s id — keep it: check-status, GET /drops/{id}, previews and post attachment all key on it.
buyUrlstringWith an app key: your app’s plain buy link id (/buy/{linkId}) — created by POST /drops; reads return it when it exists, else /buy/{productId} (a drop your app created still counts for it). With a personal key: /buy/{productId}. For a per-fan reference, create a link with POST /api/external/v1/links.
Format: uri
linkIdstring | nullThe link id in buyUrl (app keys only); comes back as linkId on the sale.
mediaCountintegerHow many vault items were attached.
Example response
{
  "productId": "clxdr0p000001prod",
  "buyUrl": "https://www.dropfans.io/buy/clxdr0p000001prod",
  "mediaCount": 3
}

Errors

StatusBodyWhen
400{"error":"Invalid price"}`price` missing, not a number, NaN or negative.
400{"error":"The minimum price is $5. Set the price to free or at least $5."}Priced above 0 but below $5.
400{"error":"The maximum price on Dropfans is $750. To request an increase, contact support@dropfans.io."}Priced above $750.
400{"error":"Field \"name\" contains a prohibited word: \"…\"","field":"name","matchedWord":"…"}The name or description tripped the word filter — a three-field envelope unique to this endpoint (posts use a two-field 422 for the same class of failure).
400{"error":"vaultItemIds must be a non-empty array"}Missing or empty media list.
400{"error":"Maximum 10 media items allowed per drop"}More than 10 ids.
400{"error":"Cannot use hidden vault items"}One of the items was deleted (hidden).
401{"error":"Unauthorized","code":"unauthorized"}Missing or invalid API key.
403{"error":"You do not own all selected vault items"}An id belongs to another creator.
404{"error":"One or more vault items not found"}An id does not exist.
500{"error":"Failed to create drop"}Write failed — retry later.
400{"error":"X-Dropfans-Account must be an account id (from GET /api/external/agency/creators), not a username.","code":"invalid_account_header"}`X-Dropfans-Account` is not an account id.
400{"error":"X-Dropfans-Account names a different account than the path — send one or the other.","code":"account_mismatch"}Called under /v1/creators/{creatorId}/ with an `X-Dropfans-Account` naming another account.
403{"error":"This key cannot act for that account.","code":"account_not_managed"}The creator in the path (or `X-Dropfans-Account`) is one this key cannot act for: no ACCEPTED management by your agency and not an account your app onboarded (or it no longer holds a key bound to your app), a key minted for one creator, or someone is suspended, banned or deleted. An unknown id gets the same answer.
403{"error":"The agency does not have permission for this on that account.","code":"permission_denied","permission":"canManageDrops"}For a managed creator: the agency lacks `canManageDrops` on that account.
403{"error":"This app does not have the drops API category enabled. Contact support to enable it.","code":"api_category_disabled","category":"drops"}Your app has the Drops & checkout links [API category](/developers/concepts/api-categories) switched off.

Rate limiting

Every response carries the X-RateLimit-Tier header and, on limited tiers, the per-minute and per-day trios — read X-RateLimit-Remaining and X-RateLimit-Reset instead of hardcoding limits. Details in Rate limits.

Code samples

curl -X POST "https://www.dropfans.io/api/external/v1/drops" \
  -H "Authorization: Bearer $DROPFANS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Beach set — 6 photos",
  "price": 25,
  "vaultItemIds": [
    "clxv1a2b30001item",
    "clxv1a2b30002item",
    "clxv1a2b30003item"
  ]
}'

Notes

The drop's moderation status is computed from its media at creation (REJECTED/FLAGGED wins, else PENDING if any item is pending, else APPROVED). Read it back with GET /api/external/v1/drops/{id}.

Questions? support@dropfans.io