Request a payout
Request a payout of the account's **full** available balance — exactly what "Pay out funds" does in the dashboard.
/api/external/payouts/requestsNewRequest a payout of the account's full available balance — exactly what "Pay out funds" does in the dashboard.
One request is created per side (creator, agency, affiliate, share) that has money and no open request; each is reviewed and paid on its own. There is no amount: partial payouts are not possible.
Idempotency-Key header required (1–255 printable characters, e.g. a UUID per payout you intend). Sending the same key with the same body again returns the original requests (201, with Idempotent-Replayed: true) instead of a second payout; the same key with a different body is refused with 409 idempotency_conflict. Keys are scoped to the account and your app (or, for a personal key, that key), so another app can never replay or block yours. A second call with the same key while the first is still running gets 409 payout_busy; retry it and it replays the first one's answer. Retry network errors with the same key.
Checked in this order, each with its own code: ID check (kyc_required) → payouts enabled (payouts_disabled) → not a buyer account (consumer_account) → a default payout method (no_method) → the payout wallet activated if the method is a MassPay wallet (masspay_not_activated) → the minimum (below_minimum) → no open request (request_open) → no payout being sent (in_flight). GET /payouts/summary reports the same gates up front.
The key's own account only: X-Dropfans-Account is refused, and so is a key an agency minted for an account it manages (403 agency_key_not_allowed) — an agency can never request a payout for a creator it manages.
At launch this endpoint answers 403 first_party_only to every other app. The read endpoints of this group are open to every key.
Authentication
Send the creator's API key as a bearer token: Authorization: Bearer dpfn_…. See Authentication & API keys.
Request body
Content type: application/json — Optional — an empty body is fine.
| Name | Type | Required | Description |
|---|---|---|---|
note | string | null | Optional | A note for the Dropfans team, shown with the request. Max length: 500 |
{
"note": "October"
}Responses
| Name | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
requests | Payout[] | One payout request per side that had money and no open request (kind request).Show child attributes
|
{
"requests": [
{
"id": "clxpr0001request",
"kind": "request",
"status": "requested",
"amountCents": 34210,
"currency": "USD",
"side": "creator",
"sides": {
"creatorCents": 34210,
"agencyCents": 0,
"affiliateCents": 0,
"shareCents": 0
},
"method": {
"type": "MASSPAY",
"label": "Payout wallet · SWE"
},
"note": "October",
"failureMessage": null,
"invoiceNumber": null,
"requestId": null,
"payoutId": null,
"createdAt": "2026-10-30T09:12:00.000Z",
"initiatedAt": null,
"paidAt": null,
"failedAt": null,
"reversedAt": null,
"reversalOfId": null
}
]
}Errors
| Status | Body | When |
|---|---|---|
| 400 | {"error":"Send an Idempotency-Key header (a unique value per payout request, e.g. a UUID).","code":"idempotency_key_required"} | No `Idempotency-Key` header (`invalid_idempotency_key` when it is malformed). |
| 400 | {"error":"note must be at most 500 characters","code":"invalid_note"} | `note` is not a string or too long. |
| 400 | {"error":"Invalid JSON body"} | The body is not valid JSON. |
| 400 | {"error":"Add a payout method before requesting a payout.","code":"no_method"} | No default payout method. |
| 400 | {"error":"Activate your payout wallet before requesting a payout.","code":"masspay_not_activated"} | The default method is a MassPay wallet the payee has not activated yet. |
| 400 | {"error":"Minimum payout is $20.00.","code":"below_minimum"} | The available balance is below the account’s minimum (or not positive). |
| 401 | {"error":"Unauthorized","code":"unauthorized"} | Missing or invalid API key. |
| 403 | {"error":"Verify your identity (KYC) before requesting a payout.","code":"kyc_required"} | The account has not passed the ID check. |
| 403 | {"error":"Payouts are not enabled on your account yet.","code":"payouts_disabled"} | Dropfans has paused payouts for the account. |
| 403 | {"error":"Payouts are not available for this account","code":"consumer_account"} | A buyer account. |
| 403 | {"error":"Payout requests need the account’s own key — a key an agency minted for a managed account cannot request or cancel payouts.","code":"agency_key_not_allowed"} | The key was minted by an agency for an account it manages. |
| 403 | {"error":"This endpoint is only available to Dropfans-operated integrations.","code":"first_party_only"} | During launch, payout requests are open to Dropfans-operated integrations only. |
| 409 | {"error":"You already have a payout request awaiting review.","code":"request_open"} | Every side with money already has an open request. |
| 409 | {"error":"A payout is already in progress. Try again once it has settled.","code":"in_flight"} | A payout is pending or processing. |
| 409 | {"error":"Another payout operation is running for this account. Try again in a moment.","code":"payout_busy"} | Another payout operation holds the account’s payout lock (e.g. a concurrent request). Retry with the same key. |
| 409 | {"error":"This Idempotency-Key was already used with a different request body.","code":"idempotency_conflict"} | The key was used before with another body. |
| 400 | {"error":"This endpoint only acts as the key’s own account — send it without X-Dropfans-Account.","code":"account_header_not_allowed"} | `X-Dropfans-Account` names another account. An agency can never request or cancel a payout for a creator it manages. |
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/payouts/requests" \
-H "Authorization: Bearer $DROPFANS_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"note":"October"}'import { randomUUID } from 'node:crypto';
// Keep the key with your record of this payout and reuse it on retries.
const idempotencyKey = randomUUID();
const res = await fetch('https://www.dropfans.io/api/external/payouts/requests', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DROPFANS_API_KEY}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ note: 'October' }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.code}: ${data.error}`);
console.log(data.requests);import os, uuid, requests
# Keep the key with your record of this payout and reuse it on retries.
idempotency_key = str(uuid.uuid4())
res = requests.post(
"https://www.dropfans.io/api/external/payouts/requests",
headers={
"Authorization": f"Bearer {os.environ['DROPFANS_API_KEY']}",
"Idempotency-Key": idempotency_key,
},
json={"note": "October"},
)
res.raise_for_status()
print(res.json()["requests"])Questions? [email protected]
