Earnings summary: totals, sources and a day / week series
API reference

Earnings summary: totals, sources and a day / week series

Totals for all time, this month and your window, a breakdown by source (drop, tip, subscription) and a zero-filled day or week series, in integer cents.

View as MarkdownUpdated Oct 31, 2026
GET/api/external/v1/earnings/summaryalso served at /api/external/earnings/summaryNew

Totals for all time, this month and your window, a breakdown by source (drop, tip, subscription) and a zero-filled day or week series, in integer cents.

The same revenue as GET /api/external/v1/earnings: refunds and chargebacks are left out, so for the same window and timezone totals.period equals its stats.totalEarningsCents (net) and stats.grossEarningsCents (gross). Each transaction is rounded to cents once, so the series always adds up to totals.period.

Days are whole local days in timezone (DST-aware: a switch day is 23 or 25 hours long). Weeks start on Monday; the first and last week are clipped to your window, and startsAt is when each bucket starts inside it.

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

GET /api/external/v1/creators/{creatorId}/earnings/summary — an agency's own key for a creator or AI persona it manages (needs canViewStats), 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.

Query parameters

NameTypeRequiredDescription
startDatestringOptionalFirst local day (YYYY-MM-DD). Defaults to 29 days before endDate. At most 366 days per window.
Format: date
endDatestringOptionalLast local day (YYYY-MM-DD), inclusive. Defaults to today in timezone.
Format: date
granularitystringOptionalSeries bucket: a local day, or a Monday-start week.
One of: day, week
Default: "day"
timezonestringOptionalIANA timezone for the days, weeks and "this month". tz is accepted too. Unlike GET /earnings, an unknown zone is a 400, not UTC.
Default: "UTC"
Format: iana-timezone

Responses

200Totals, breakdown and series. All money in cents.
NameTypeDescription
startDatestringThe window’s first day.
Format: date
endDatestringThe window’s last day (inclusive).
Format: date
timezonestringThe timezone used.
granularitystringThe series bucket.
One of: day, week
currencystringAlways USD.
totalsobjectallTime, thisMonth (the current month in timezone, up to today) and period (your window), each { grossCents, netCents, count }.
Show child attributes
allTimeobjectSince the account’s first sale.
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
thisMonthobjectThe current calendar month in timezone.
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
periodobjectYour window — equals the sum of series.
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
breakdownBySourceobjectdrop, tip and subscription for your window, each { grossCents, netCents, count }.
Show child attributes
dropobjectDrop sales.
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
tipobjectTips.
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
subscriptionobjectSubscription payments (first charges and renewals).
Show child attributes
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerNumber of transactions.
seriesobject[]One point per day or week of the window, oldest first, zero-filled.
Show child attributes
datestringThe local day, or the Monday the week starts on (can be before startDate).
Format: date
startsAtstringWhen the bucket starts, clipped to the window.
Format: date-time
grossCentsintegerBuyer-paid minus VAT, before the platform fee.
netCentsintegerThe creator’s earnings after the platform fee.
countintegerTransactions in the bucket.
Example response
{
  "startDate": "2026-10-26",
  "endDate": "2026-10-27",
  "timezone": "Europe/Stockholm",
  "granularity": "day",
  "currency": "USD",
  "totals": {
    "allTime": {
      "grossCents": 2480000,
      "netCents": 1984000,
      "count": 912
    },
    "thisMonth": {
      "grossCents": 214180,
      "netCents": 182050,
      "count": 41
    },
    "period": {
      "grossCents": 22300,
      "netCents": 18950,
      "count": 7
    }
  },
  "breakdownBySource": {
    "drop": {
      "grossCents": 15000,
      "netCents": 12750,
      "count": 4
    },
    "tip": {
      "grossCents": 5300,
      "netCents": 4500,
      "count": 2
    },
    "subscription": {
      "grossCents": 2000,
      "netCents": 1700,
      "count": 1
    }
  },
  "series": [
    {
      "date": "2026-10-26",
      "startsAt": "2026-10-25T23:00:00.000Z",
      "grossCents": 12500,
      "netCents": 10620,
      "count": 4
    },
    {
      "date": "2026-10-27",
      "startsAt": "2026-10-26T23:00:00.000Z",
      "grossCents": 9800,
      "netCents": 8330,
      "count": 3
    }
  ]
}

Errors

StatusBodyWhen
400{"error":"timezone must be an IANA timezone name, e.g. Europe/Stockholm","code":"invalid_timezone"}Unknown `timezone`.
400{"error":"startDate and endDate must be YYYY-MM-DD dates","code":"invalid_date"}Malformed or impossible date (e.g. 2026-02-31).
400{"error":"endDate must be on or after startDate","code":"invalid_date_range"}`startDate` is after `endDate`.
400{"error":"Date range too large — at most 366 days.","code":"range_too_large"}The window is longer than 366 days.
400{"error":"granularity must be day or week","code":"invalid_granularity"}Any other `granularity`.
401{"error":"Unauthorized","code":"unauthorized"}Missing or invalid API key.
500{"error":"Failed to fetch the earnings summary"}Query 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":"canViewStats"}For a managed creator: the agency lacks `canViewStats` on that account.
403{"error":"This app does not have the earnings API category enabled. Contact support to enable it.","code":"api_category_disabled","category":"earnings"}Your app has the Earnings & balance [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 "https://www.dropfans.io/api/external/v1/earnings/summary?startDate=2026-10-01&endDate=2026-10-31&timezone=Europe%2FStockholm" \
  -H "Authorization: Bearer $DROPFANS_API_KEY"

Questions? [email protected]