List paid tips (per-fan references)
API reference

List paid tips (per-fan references)

Paid tips of the key's account, newest first — the polling twin of the [tip.paid webhook](/developers/webhooks/overview).

View as MarkdownUpdated Oct 23, 2026
GET/api/external/v1/tipsalso served at /api/external/tipsNew

Paid tips of the key's account, newest first — the polling twin of the tip.paid webhook.

Filter by externalRef to answer "did this fan tip?" for a tip link you sent, or by since to sweep. Each tip carries the fan's message. Refunded and charged-back tips stay in the list with their status — act on status: "paid" 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

GET /api/external/v1/creators/{creatorId}/tips — 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
externalRefstringOptionalOnly tips made through links carrying this reference.
Max length: 32
Pattern: ^[A-Za-z0-9_-]{1,32}$
sincestringOptionalOnly tips paid at or after this time.
Format: date-time
limitintegerOptionalPage size.
Default: 50
Min: 1
Max: 100
cursorstringOptionalnextCursor from the previous page.

Responses

200A page of tips.
NameTypeDescription
tipsTip[]Newest first.
Show child attributes
tipIdstringThe tip id. Unique per tip — dedupe on it.
accountIdstringThe creator who was tipped (the account behind the key).
externalRefstring | nullYour per-fan reference from the tip link the fan opened (&m= on the web, tm_{cents}_{ref}_{username} in Telegram). Null when the fan came without one. Not proof of identity — the fan can edit the link.
Max length: 32
Pattern: ^[A-Za-z0-9_-]{1,32}$
linkIdstring | nullThe link id (POST /api/external/v1/links) it came through; null for template links. Its externalRef is the link’s.
amountCentsintegerGross fan-paid total in **cents** (VAT included).
netAmountCentsintegerWhat the creator keeps from this tip in **cents** (after the platform fee and VAT; before any agency split).
platformFeeCentsintegerPlatform fee in cents.
taxCentsintegerVAT in cents (retained, not paid out).
currencystringAlways USD.
One of: USD
messagestring | nullThe message the fan wrote with the tip, if any.
Max length: 280
paidAtstring | nullWhen the payment settled (UTC).
Format: date-time
paidWithstringCard, or the fan’s prepaid wallet credits.
One of: card, credits
statusstringCurrent state of the tip.
One of: paid, refunded, charged_back
tipperobjectWho tipped. Every field may be null for a guest checkout.
Show child attributes
idstring | nullThe fan’s account id, when signed in.
emailstring | nullBilling / account email.
Format: email
telegramUserIdstring | nullTelegram user id (as a string) when the fan used the Mini App — cross-check it against your externalRef.
telegramUsernamestring | nullTelegram @username without the @, when known.
nextCursorstring | nullPass as cursor for the next page; null on the last page.
Example response
{
  "tips": [
    {
      "tipId": "clxtp0001tip",
      "accountId": "clx2f8a1b0001qw3k",
      "externalRef": "fan-48213377",
      "amountCents": 1100,
      "currency": "USD",
      "message": "For the new set 💕",
      "paidAt": "2026-10-23T16:20:00.000Z",
      "paidWith": "card",
      "status": "paid",
      "tipper": {
        "id": "clxbu0001buyer",
        "email": "fan@example.com",
        "telegramUserId": "48213377",
        "telegramUsername": "fan_one"
      }
    }
  ],
  "nextCursor": null
}

Errors

StatusBodyWhen
400{"error":"externalRef must be 1–32 of A-Z a-z 0-9 _ -"}Malformed reference.
400{"error":"since must be an ISO date"}Unparseable `since`.
401{"error":"Unauthorized","code":"unauthorized"}Missing or invalid API key.
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/tips?externalRef=fan-48213377" \
  -H "Authorization: Bearer $DROPFANS_API_KEY"

Questions? support@dropfans.io