> ## Documentation Index
> Fetch the complete documentation index at: https://www.dropfans.io/developers/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /api/external/crm/stats — Dashboard stats

> Your integration dashboard’s Dashboard tab as data: revenue, booked commission, sales and new accounts, as totals plus zero-filled hour, day, week or month buckets.

- Source: https://www.dropfans.io/developers/reference/get-crm-stats
- Section: API reference
- OpenAPI: https://www.dropfans.io/developers/openapi.json

Your integration dashboard’s Dashboard tab as data: revenue, booked commission, sales and new accounts, as totals plus zero-filled hour, day, week or month buckets.

It returns revenue through your app’s links, the commission booked for your app owner, sales and newly connected accounts. The numbers are the dashboard’s own: same sales, same day boundaries (Europe/Stockholm unless you pass `tz`), same automatic bucket size. Amounts are integer **US cents, excluding tax, before our platform fee**; refunded and charged-back sales are left out. `earningsCents` is the commission **booked** on those sales — it is paid out with your app owner’s earnings, so booked is not the same as already paid.

## Authentication

`Authorization: Bearer dpfn_...` — an API key generated in the dashboard (Vault → API Connect). By default the key acts for the one account it belongs to. Missing or invalid keys return 401 `{"error":"Unauthorized","code":"unauthorized"}`.

## Query parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `startDate` | string | yes | First day, YYYY-MM-DD (inclusive, in `tz`). |
| `endDate` | string | yes | Last day, YYYY-MM-DD (inclusive, in `tz`). At most 366 days after startDate. |
| `tz` | string |  | IANA time zone the calendar days (and buckets) are cut in. Defaults to Europe/Stockholm, like your dashboard. |
| `granularity` | `hour` \\| `day` \\| `week` \\| `month` |  | Bucket size. Leave it out for the dashboard’s automatic pick (hour for one day, day up to 30 days, week up to 90, month beyond). `hour` is allowed for up to 3 days. |

## Responses

### 200

Totals and the bucket series.

| Field | Type | Required | Description |
|---|---|---|---|
| `startDate` | string | yes | As requested. |
| `endDate` | string | yes | As requested. |
| `tz` | string | yes | The zone days and buckets are cut in. |
| `granularity` | `hour` \\| `day` \\| `week` \\| `month` | yes | Bucket size used (the one you asked for, or the automatic pick). |
| `currency` | `USD` | yes | Currency of every *Cents field. |
| `totals` | object | yes | The whole range. Counts equal the sum of `series`; cent amounts are rounded once over the range, so they can differ from the summed buckets by a cent. |
| `totals.revenueCents` | integer | yes | US cents, excl. tax, before our platform fee; reversals left out. |
| `totals.earningsCents` | integer | yes | Commission booked for your app owner, US cents. |
| `totals.transactions` | integer | yes | Sales in the range. |
| `totals.newConnectedAccounts` | integer | yes | Accounts first connected in the range. |
| `totals.connectedAccountsNow` | integer | yes | Accounts connected to your app right now (your app generated their links most recently). Not range-bound. |
| `series` | CrmStatsBucket[] | yes | Every bucket of the range, oldest first, zero-filled. |

```json
{
  "startDate": "2026-10-27",
  "endDate": "2026-10-29",
  "tz": "Europe/Stockholm",
  "granularity": "day",
  "currency": "USD",
  "totals": {
    "revenueCents": 6000,
    "earningsCents": 300,
    "transactions": 4,
    "newConnectedAccounts": 1,
    "connectedAccountsNow": 18
  },
  "series": [
    {
      "bucket": "2026-10-27",
      "start": "2026-10-26T23:00:00.000Z",
      "revenueCents": 0,
      "earningsCents": 0,
      "transactions": 0,
      "newConnectedAccounts": 0
    },
    {
      "bucket": "2026-10-28",
      "start": "2026-10-27T23:00:00.000Z",
      "revenueCents": 4500,
      "earningsCents": 225,
      "transactions": 3,
      "newConnectedAccounts": 1
    },
    {
      "bucket": "2026-10-29",
      "start": "2026-10-28T23:00:00.000Z",
      "revenueCents": 1500,
      "earningsCents": 75,
      "transactions": 1,
      "newConnectedAccounts": 0
    }
  ]
}
```

## Errors

| Status | Body | When |
|---|---|---|
| 400 | `{"error":"startDate must be a real calendar day, YYYY-MM-DD.","code":"invalid_input","field":"startDate"}` | `startDate` / `endDate` missing (stats) or not a YYYY-MM-DD day. |
| 400 | `{"error":"endDate must be on or after startDate.","code":"invalid_input","field":"endDate"}` | `endDate` is before `startDate`. |
| 400 | `{"error":"The range can be at most 366 days.","code":"invalid_input","field":"endDate"}` | More than 366 days. |
| 400 | `{"error":"tz must be an IANA time zone, e.g. Europe/Stockholm or America/New_York.","code":"invalid_input","field":"tz"}` | Unknown `tz`. |
| 400 | `{"error":"granularity=hour is only allowed for ranges of up to 3 days.","code":"invalid_input","field":"granularity"}` | `granularity=hour` over more than 3 days, or an unknown granularity. |
| 401 | `{"error":"Unauthorized","code":"unauthorized"}` | Missing or invalid API key. |
| 403 | `{"error":"This endpoint needs a key bound to an approved app.","code":"app_key_required"}` | A Personal key was used. |
| 403 | `{"error":"Use the app owner's key for this endpoint.","code":"owner_key_required"}` | The key was minted by a creator for themselves. App-level calls need a key held by your app owner: their own, or one their agency minted for its personas or managed creators. |
| 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` was sent. These endpoints always answer for the key’s app. |

## Notes

Buckets are local to `tz`: on a day the clocks go forward there are 23 hourly buckets; on a day they go back the repeated hour is a single bucket (24). Each bucket’s `start` is its exact UTC instant.

## Rate limiting

Per-key fixed windows by tier (Personal 60/min · 5,000/day; approved apps 300/min · 50,000/day; Dropfans-operated integrations exempt). Read the live values from X-RateLimit-Tier, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and their -Day variants; a 429 carries Retry-After and `{"error":"Rate limit exceeded","code":"rate_limited"}`. See [Rate limits](https://www.dropfans.io/developers/concepts/rate-limits.md).

## Code samples

### curl

```bash
curl "https://www.dropfans.io/api/external/crm/stats?startDate=2026-10-01&endDate=2026-10-30&tz=America%2FNew_York" \
  -H "Authorization: Bearer $DROPFANS_API_KEY"
```

### Node

```javascript
const res = await fetch(`https://www.dropfans.io/api/external/crm/stats?startDate=2026-10-01&endDate=2026-10-30&tz=America%2FNew_York`, {
  headers: {
    Authorization: `Bearer ${process.env.DROPFANS_API_KEY}`,
  },
});
console.log(await res.json());
```

### Python

```python
import os
import requests

res = requests.get(
    "https://www.dropfans.io/api/external/crm/stats",
    headers={"Authorization": f"Bearer {os.environ['DROPFANS_API_KEY']}"},
    params={"startDate": "2026-10-01", "endDate": "2026-10-30", "tz": "America/New_York"},
)
print(res.json())
```

## OpenAPI

```json
{
  "method": "GET",
  "path": "/api/external/crm/stats",
  "operationId": "getCrmStats",
  "tags": [
    "crm"
  ],
  "summary": "Dashboard stats",
  "description": "Your integration dashboard’s Dashboard tab as data: revenue, booked commission, sales and new accounts, as totals plus zero-filled hour, day, week or month buckets.\n\nIt returns revenue through your app’s links, the commission booked for your app owner, sales and newly connected accounts. The numbers are the dashboard’s own: same sales, same day boundaries (Europe/Stockholm unless you pass `tz`), same automatic bucket size. Amounts are integer **US cents, excluding tax, before our platform fee**; refunded and charged-back sales are left out. `earningsCents` is the commission **booked** on those sales — it is paid out with your app owner’s earnings, so booked is not the same as already paid.",
  "parameters": [
    {
      "name": "startDate",
      "in": "query",
      "required": true,
      "description": "First day, YYYY-MM-DD (inclusive, in `tz`).",
      "schema": {
        "type": "string",
        "format": "date"
      },
      "example": "2026-10-01"
    },
    {
      "name": "endDate",
      "in": "query",
      "required": true,
      "description": "Last day, YYYY-MM-DD (inclusive, in `tz`). At most 366 days after startDate.",
      "schema": {
        "type": "string",
        "format": "date"
      },
      "example": "2026-10-30"
    },
    {
      "name": "tz",
      "in": "query",
      "required": false,
      "description": "IANA time zone the calendar days (and buckets) are cut in. Defaults to Europe/Stockholm, like your dashboard.",
      "schema": {
        "type": "string",
        "default": "Europe/Stockholm",
        "format": "iana-timezone"
      },
      "example": "America/New_York"
    },
    {
      "name": "granularity",
      "in": "query",
      "required": false,
      "description": "Bucket size. Leave it out for the dashboard’s automatic pick (hour for one day, day up to 30 days, week up to 90, month beyond). `hour` is allowed for up to 3 days.",
      "schema": {
        "type": "string",
        "enum": [
          "hour",
          "day",
          "week",
          "month"
        ]
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Totals and the bucket series.",
      "headers": {
        "X-RateLimit-Tier": {
          "description": "Rate-limit tier of the key: personal, app or first_party (first_party is unlimited).",
          "schema": {
            "type": "string",
            "enum": [
              "personal",
              "app",
              "first_party"
            ]
          }
        },
        "X-RateLimit-Limit": {
          "description": "Requests allowed per minute for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining": {
          "description": "Requests left in the current minute window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset": {
          "description": "Epoch seconds when the minute window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Limit-Day": {
          "description": "Requests allowed per UTC day for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining-Day": {
          "description": "Requests left in the current UTC day window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset-Day": {
          "description": "Epoch seconds when the day window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-Dropfans-Account": {
          "description": "The id of the account this request acted on — the key’s own account, or the managed account named in the X-Dropfans-Account request header. Assert it when acting for several accounts.",
          "schema": {
            "type": "string"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "startDate": {
                "type": "string",
                "description": "As requested.",
                "format": "date",
                "example": "2026-10-01"
              },
              "endDate": {
                "type": "string",
                "description": "As requested.",
                "format": "date",
                "example": "2026-10-30"
              },
              "tz": {
                "type": "string",
                "description": "The zone days and buckets are cut in.",
                "format": "iana-timezone",
                "example": "Europe/Stockholm"
              },
              "granularity": {
                "type": "string",
                "description": "Bucket size used (the one you asked for, or the automatic pick).",
                "enum": [
                  "hour",
                  "day",
                  "week",
                  "month"
                ]
              },
              "currency": {
                "type": "string",
                "description": "Currency of every *Cents field.",
                "enum": [
                  "USD"
                ]
              },
              "totals": {
                "type": "object",
                "properties": {
                  "revenueCents": {
                    "type": "integer",
                    "description": "US cents, excl. tax, before our platform fee; reversals left out.",
                    "example": 128000
                  },
                  "earningsCents": {
                    "type": "integer",
                    "description": "Commission booked for your app owner, US cents.",
                    "example": 6400
                  },
                  "transactions": {
                    "type": "integer",
                    "description": "Sales in the range.",
                    "example": 42
                  },
                  "newConnectedAccounts": {
                    "type": "integer",
                    "description": "Accounts first connected in the range.",
                    "example": 5
                  },
                  "connectedAccountsNow": {
                    "type": "integer",
                    "description": "Accounts connected to your app right now (your app generated their links most recently). Not range-bound.",
                    "example": 18
                  }
                },
                "required": [
                  "revenueCents",
                  "earningsCents",
                  "transactions",
                  "newConnectedAccounts",
                  "connectedAccountsNow"
                ],
                "description": "The whole range. Counts equal the sum of `series`; cent amounts are rounded once over the range, so they can differ from the summed buckets by a cent."
              },
              "series": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "bucket": {
                      "type": "string",
                      "description": "Bucket key in `tz` local time: `YYYY-MM-DDTHH` (hour), `YYYY-MM-DD` (day; for week the Monday), `YYYY-MM` (month). On a day the clocks go back, the repeated hour is one bucket.",
                      "example": "2026-10-28"
                    },
                    "start": {
                      "type": "string",
                      "description": "The UTC instant the bucket begins, clamped to the start of the range (a week or month bucket can begin before startDate).",
                      "format": "date-time"
                    },
                    "revenueCents": {
                      "type": "integer",
                      "description": "Sales through your app’s links in the bucket, US cents, excl. tax, before our platform fee. Refunded and charged-back sales are left out.",
                      "example": 4500
                    },
                    "earningsCents": {
                      "type": "integer",
                      "description": "Commission booked for your app owner on those sales, US cents. Booked, not necessarily paid out yet.",
                      "example": 225
                    },
                    "transactions": {
                      "type": "integer",
                      "description": "Number of those sales.",
                      "example": 3
                    },
                    "newConnectedAccounts": {
                      "type": "integer",
                      "description": "Accounts your app issued links for the first time in the bucket.",
                      "example": 1
                    }
                  },
                  "required": [
                    "bucket",
                    "start",
                    "revenueCents",
                    "earningsCents",
                    "transactions",
                    "newConnectedAccounts"
                  ]
                },
                "description": "Every bucket of the range, oldest first, zero-filled."
              }
            },
            "required": [
              "startDate",
              "endDate",
              "tz",
              "granularity",
              "currency",
              "totals",
              "series"
            ]
          },
          "example": {
            "startDate": "2026-10-27",
            "endDate": "2026-10-29",
            "tz": "Europe/Stockholm",
            "granularity": "day",
            "currency": "USD",
            "totals": {
              "revenueCents": 6000,
              "earningsCents": 300,
              "transactions": 4,
              "newConnectedAccounts": 1,
              "connectedAccountsNow": 18
            },
            "series": [
              {
                "bucket": "2026-10-27",
                "start": "2026-10-26T23:00:00.000Z",
                "revenueCents": 0,
                "earningsCents": 0,
                "transactions": 0,
                "newConnectedAccounts": 0
              },
              {
                "bucket": "2026-10-28",
                "start": "2026-10-27T23:00:00.000Z",
                "revenueCents": 4500,
                "earningsCents": 225,
                "transactions": 3,
                "newConnectedAccounts": 1
              },
              {
                "bucket": "2026-10-29",
                "start": "2026-10-28T23:00:00.000Z",
                "revenueCents": 1500,
                "earningsCents": 75,
                "transactions": 1,
                "newConnectedAccounts": 0
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "`startDate` / `endDate` missing (stats) or not a YYYY-MM-DD day. Also: `endDate` is before `startDate`. Also: More than 366 days. Also: Unknown `tz`. Also: `granularity=hour` over more than 3 days, or an unknown granularity. Also: `X-Dropfans-Account` was sent. These endpoints always answer for the key’s app.",
      "headers": {
        "X-RateLimit-Tier": {
          "description": "Rate-limit tier of the key: personal, app or first_party (first_party is unlimited).",
          "schema": {
            "type": "string",
            "enum": [
              "personal",
              "app",
              "first_party"
            ]
          }
        },
        "X-RateLimit-Limit": {
          "description": "Requests allowed per minute for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining": {
          "description": "Requests left in the current minute window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset": {
          "description": "Epoch seconds when the minute window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Limit-Day": {
          "description": "Requests allowed per UTC day for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining-Day": {
          "description": "Requests left in the current UTC day window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset-Day": {
          "description": "Epoch seconds when the day window resets.",
          "schema": {
            "type": "integer"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "Human-readable message naming the offending field and word.",
                "example": "Field \"name\" contains a prohibited word: \"…\""
              },
              "field": {
                "type": "string",
                "description": "Which request field tripped the filter (\"name\" or \"description\")."
              },
              "matchedWord": {
                "type": "string",
                "description": "The prohibited word."
              }
            },
            "required": [
              "error",
              "field",
              "matchedWord"
            ]
          },
          "example": {
            "error": "startDate must be a real calendar day, YYYY-MM-DD.",
            "code": "invalid_input",
            "field": "startDate"
          }
        }
      }
    },
    "401": {
      "description": "Missing or invalid API key.",
      "headers": {
        "X-RateLimit-Tier": {
          "description": "Rate-limit tier of the key: personal, app or first_party (first_party is unlimited).",
          "schema": {
            "type": "string",
            "enum": [
              "personal",
              "app",
              "first_party"
            ]
          }
        },
        "X-RateLimit-Limit": {
          "description": "Requests allowed per minute for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining": {
          "description": "Requests left in the current minute window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset": {
          "description": "Epoch seconds when the minute window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Limit-Day": {
          "description": "Requests allowed per UTC day for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining-Day": {
          "description": "Requests left in the current UTC day window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset-Day": {
          "description": "Epoch seconds when the day window resets.",
          "schema": {
            "type": "integer"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "Human-readable message.",
                "example": "Rate limit exceeded"
              },
              "code": {
                "type": "string",
                "description": "Machine-readable code: unauthorized, app_suspended, first_party_only, rate_limited, username_required, invalid_account_header, account_not_managed, permission_denied, account_header_not_allowed, agency_key_required — plus endpoint-specific codes listed on each reference page.",
                "example": "rate_limited"
              }
            },
            "required": [
              "error",
              "code"
            ]
          },
          "example": {
            "error": "Unauthorized",
            "code": "unauthorized"
          }
        }
      }
    },
    "403": {
      "description": "A Personal key was used. Also: The key was minted by a creator for themselves. App-level calls need a key held by your app owner: their own, or one their agency minted for its personas or managed creators.",
      "headers": {
        "X-RateLimit-Tier": {
          "description": "Rate-limit tier of the key: personal, app or first_party (first_party is unlimited).",
          "schema": {
            "type": "string",
            "enum": [
              "personal",
              "app",
              "first_party"
            ]
          }
        },
        "X-RateLimit-Limit": {
          "description": "Requests allowed per minute for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining": {
          "description": "Requests left in the current minute window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset": {
          "description": "Epoch seconds when the minute window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Limit-Day": {
          "description": "Requests allowed per UTC day for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining-Day": {
          "description": "Requests left in the current UTC day window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset-Day": {
          "description": "Epoch seconds when the day window resets.",
          "schema": {
            "type": "integer"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "Human-readable message.",
                "example": "Rate limit exceeded"
              },
              "code": {
                "type": "string",
                "description": "Machine-readable code: unauthorized, app_suspended, first_party_only, rate_limited, username_required, invalid_account_header, account_not_managed, permission_denied, account_header_not_allowed, agency_key_required — plus endpoint-specific codes listed on each reference page.",
                "example": "rate_limited"
              }
            },
            "required": [
              "error",
              "code"
            ]
          },
          "example": {
            "error": "This endpoint needs a key bound to an approved app.",
            "code": "app_key_required"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit exceeded for the current minute or day window. Wait Retry-After seconds and retry.",
      "headers": {
        "X-RateLimit-Tier": {
          "description": "Rate-limit tier of the key: personal, app or first_party (first_party is unlimited).",
          "schema": {
            "type": "string",
            "enum": [
              "personal",
              "app",
              "first_party"
            ]
          }
        },
        "X-RateLimit-Limit": {
          "description": "Requests allowed per minute for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining": {
          "description": "Requests left in the current minute window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset": {
          "description": "Epoch seconds when the minute window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Limit-Day": {
          "description": "Requests allowed per UTC day for this key (absent on first_party).",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Remaining-Day": {
          "description": "Requests left in the current UTC day window.",
          "schema": {
            "type": "integer"
          }
        },
        "X-RateLimit-Reset-Day": {
          "description": "Epoch seconds when the day window resets.",
          "schema": {
            "type": "integer"
          }
        },
        "Retry-After": {
          "description": "Seconds to wait before retrying (sent with 429s).",
          "schema": {
            "type": "integer"
          }
        }
      },
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "error": {
                "type": "string",
                "description": "Human-readable message.",
                "example": "Rate limit exceeded"
              },
              "code": {
                "type": "string",
                "description": "Machine-readable code: unauthorized, app_suspended, first_party_only, rate_limited, username_required, invalid_account_header, account_not_managed, permission_denied, account_header_not_allowed, agency_key_required — plus endpoint-specific codes listed on each reference page.",
                "example": "rate_limited"
              }
            },
            "required": [
              "error",
              "code"
            ]
          },
          "example": {
            "error": "Rate limit exceeded",
            "code": "rate_limited"
          }
        }
      }
    }
  },
  "x-codeSamples": [
    {
      "lang": "cURL",
      "label": "curl",
      "source": "curl \"https://www.dropfans.io/api/external/crm/stats?startDate=2026-10-01&endDate=2026-10-30&tz=America%2FNew_York\" \\\n  -H \"Authorization: Bearer $DROPFANS_API_KEY\""
    },
    {
      "lang": "JavaScript",
      "label": "Node",
      "source": "const res = await fetch(`https://www.dropfans.io/api/external/crm/stats?startDate=2026-10-01&endDate=2026-10-30&tz=America%2FNew_York`, {\n  headers: {\n    Authorization: `Bearer ${process.env.DROPFANS_API_KEY}`,\n  },\n});\nconsole.log(await res.json());"
    },
    {
      "lang": "Python",
      "source": "import os\nimport requests\n\nres = requests.get(\n    \"https://www.dropfans.io/api/external/crm/stats\",\n    headers={\"Authorization\": f\"Bearer {os.environ['DROPFANS_API_KEY']}\"},\n    params={\"startDate\": \"2026-10-01\", \"endDate\": \"2026-10-30\", \"tz\": \"America/New_York\"},\n)\nprint(res.json())"
    }
  ],
  "x-dropfans-docs": "https://www.dropfans.io/developers/reference/get-crm-stats"
}
```

---

Previous: [Get your app](https://www.dropfans.io/developers/reference/get-crm-app.md) · Next: [List sales through your app](https://www.dropfans.io/developers/reference/list-crm-transactions.md) · All pages: [llms.txt](https://www.dropfans.io/developers/llms.txt)
