# GrowPanel for Developers

> REST API reference, CLI, MCP server, and integration guides.
> Built 2026-04-19T17:45:51.211Z · source: https://growpanel.io/developers/

---

## Building Integrations
<!-- url: https://growpanel.io/developers/building-integrations -->

This guide explains how to connect any billing system to GrowPanel. Whether you have a custom-built billing platform, use a service we don't natively support, or want to build a public integration, this guide covers everything you need to know.

---

## How GrowPanel calculates metrics

Before building an integration, it helps to understand how GrowPanel turns raw billing data into subscription metrics.

### The data model

GrowPanel works with three core data types:

| Data type | Purpose |
|-----------|---------|
| **Customers** | Who is paying you |
| **Plans** | What they're paying for (pricing, billing interval) |
| **Invoices** | Records of what they actually paid |

From these three inputs, GrowPanel calculates all subscription metrics: MRR, ARR, churn, expansion, contraction, reactivation, cohort retention, and more.

### How invoices become MRR

The key insight is that **invoices drive everything**. GrowPanel doesn't track "subscriptions" as a separate concept—it reconstructs subscription state from invoice history.

When you send an invoice, GrowPanel:

1. Looks up the customer and plan
2. Determines the billing interval (monthly, annual, etc.)
3. Normalizes the amount to monthly (annual invoices ÷ 12)
4. Compares to the customer's previous MRR
5. Classifies the change as new, expansion, contraction, or reactivation

**Example:** A customer paying $1,200/year for an annual plan contributes $100/month MRR.

### MRR movements

GrowPanel automatically detects these movement types:

| Movement | What triggers it |
|----------|------------------|
| **New** | First invoice for a customer (or first after being churned) |
| **Expansion** | Invoice with higher MRR than previous period |
| **Contraction** | Invoice with lower MRR than previous period |
| **Churn** | No invoice in the expected billing period, or cancellation invoice |
| **Reactivation** | Invoice for a customer who previously churned |

You don't need to tell GrowPanel which movement type applies—it figures this out from the invoice sequence.

---

## What you need to send

To build an integration, you need to push three things to GrowPanel:

### 1. Customers

Basic information about who is paying you.

```json
{
  "id": "cust_123",
  "name": "Acme Inc",
  "email": "billing@acme.com",
  "country": "US",
  "created": "2024-01-15T00:00:00Z"
}
```

**Required fields:**
- `id` - Your unique identifier for this customer
- `name` - Customer or company name

**Optional but recommended:**
- `email` - For customer lookup
- `country` - For geographic segmentation
- `created` - When they became a customer
- `metadata` - Custom fields for segmentation (industry, size, etc.)

### 2. Plans

Your pricing structure.

```json
{
  "id": "plan_pro_monthly",
  "name": "Pro Monthly",
  "interval": "month",
  "interval_count": 1,
  "currency": "USD"
}
```

**Required fields:**
- `id` - Your unique identifier for this plan
- `name` - Display name
- `interval` - Billing period: `day`, `week`, `month`, `year`
- `interval_count` - Number of intervals (1 for monthly, 12 for annual)
- `currency` - Three-letter currency code

**Why interval matters:** GrowPanel uses the interval to normalize revenue to monthly. A $1,200 annual plan becomes $100 MRR.

### 3. Invoices

The actual payment records that drive all metrics.

```json
{
  "id": "inv_456",
  "customer_id": "cust_123",
  "plan_id": "plan_pro_monthly",
  "type": "subscription",
  "invoice_date": "2024-02-01T00:00:00Z",
  "amount": 9900,
  "currency": "USD",
  "period_start": "2024-02-01T00:00:00Z",
  "period_end": "2024-03-01T00:00:00Z"
}
```

**Required fields:**
- `id` - Your unique identifier for this invoice
- `customer_id` - Must match an existing customer
- `type` - One of: `subscription`, `one-time`, `refund`, `cancellation`
- `invoice_date` - When the invoice was created
- `amount` - Amount in cents (9900 = $99.00)
- `currency` - Three-letter currency code

**Required for subscription invoices:**
- `plan_id` - Must match an existing plan

**Recommended:**
- `period_start` and `period_end` - The billing period this invoice covers
- `subscription_id` - Groups invoices into a subscription

---

## Invoice types explained

The `type` field tells GrowPanel how to process the invoice:

### subscription

Regular recurring invoices. These create MRR.

```json
{
  "type": "subscription",
  "amount": 9900,
  "plan_id": "plan_pro"
}
```

### one-time

Setup fees, consulting, or other non-recurring charges. These don't affect MRR.

```json
{
  "type": "one-time",
  "amount": 50000
}
```

### refund

Partial or full refunds. Reduces MRR proportionally.

```json
{
  "type": "refund",
  "amount": -4950
}
```

### cancellation

Marks the end of a subscription. Use amount `0` to signal churn without a refund.

```json
{
  "type": "cancellation",
  "amount": 0,
  "customer_id": "cust_123"
}
```

---

## Common scenarios

### New customer signs up

1. Create the customer
2. Create the plan (if not already exists)
3. Create a `subscription` invoice

```bash
# 1. Create customer
curl -X POST https://api.growpanel.io/v1/data-sources/{id}/customers \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"id": "cust_new", "name": "New Customer", "email": "new@example.com"}'

# 2. Create invoice
curl -X POST https://api.growpanel.io/v1/data-sources/{id}/invoices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "id": "inv_001",
    "customer_id": "cust_new",
    "plan_id": "plan_pro",
    "type": "subscription",
    "invoice_date": "2024-02-01T00:00:00Z",
    "amount": 9900,
    "currency": "USD"
  }'
```

**Result:** GrowPanel records this as **New MRR** of $99.

### Customer upgrades

Send a new `subscription` invoice with the higher amount.

```json
{
  "id": "inv_002",
  "customer_id": "cust_123",
  "plan_id": "plan_enterprise",
  "type": "subscription",
  "amount": 29900,
  "invoice_date": "2024-03-01T00:00:00Z"
}
```

**Result:** GrowPanel compares to the previous invoice ($99) and records **Expansion MRR** of $200.

### Customer downgrades

Send a new `subscription` invoice with the lower amount.

```json
{
  "id": "inv_003",
  "customer_id": "cust_123",
  "plan_id": "plan_basic",
  "type": "subscription",
  "amount": 4900,
  "invoice_date": "2024-04-01T00:00:00Z"
}
```

**Result:** GrowPanel records **Contraction MRR** of $250.

### Customer cancels

Send a `cancellation` invoice with amount `0`.

```json
{
  "id": "inv_004",
  "customer_id": "cust_123",
  "type": "cancellation",
  "amount": 0,
  "invoice_date": "2024-05-01T00:00:00Z"
}
```

**Result:** GrowPanel records **Churned MRR** equal to their last invoice amount.

### Customer reactivates

After a customer has churned, send a new `subscription` invoice.

```json
{
  "id": "inv_005",
  "customer_id": "cust_123",
  "plan_id": "plan_pro",
  "type": "subscription",
  "amount": 9900,
  "invoice_date": "2024-08-01T00:00:00Z"
}
```

**Result:** GrowPanel recognizes this customer previously churned and records **Reactivation MRR** of $99.

---

## Historical data import

For accurate reporting, import your full invoice history—not just current subscriptions.

### Why history matters

GrowPanel calculates:
- **Cohort retention** - Needs to know when customers started
- **Churn trends** - Needs to see when customers left
- **Growth decomposition** - Needs the full sequence of changes

Without historical data, you'll only see current state, not trends.

### Import order

1. **Customers first** - Invoices reference customers
2. **Plans second** - Invoices reference plans
3. **Invoices last** - In chronological order

### Batch imports

For large datasets, use batch requests:

```json
{
  "invoices": [
    {"id": "inv_001", "customer_id": "cust_1", "amount": 9900, "...": "..."},
    {"id": "inv_002", "customer_id": "cust_2", "amount": 4900, "...": "..."},
    {"id": "inv_003", "customer_id": "cust_1", "amount": 9900, "...": "..."}
  ]
}
```

---

## Real-time sync

After the initial import, keep GrowPanel updated as events happen:

| Event in your system | Action in GrowPanel |
|---------------------|---------------------|
| New subscription | POST customer + invoice |
| Renewal | POST invoice |
| Upgrade/downgrade | POST invoice with new amount |
| Cancellation | POST cancellation invoice |
| Refund | POST refund invoice |

### Webhook-driven sync

If your billing system supports webhooks, trigger API calls on:

- `invoice.paid` → POST invoice
- `subscription.created` → POST customer (if new) + invoice
- `subscription.updated` → POST invoice with new amount
- `subscription.cancelled` → POST cancellation invoice
- `charge.refunded` → POST refund invoice

---

## Best practices

### Use stable IDs

Your `id` fields should be:
- **Unique** - No duplicates within a type
- **Stable** - Same customer always has the same ID
- **Immutable** - Don't change IDs over time

GrowPanel uses IDs for deduplication. If you send the same invoice ID twice, it updates rather than duplicates.

### Include all invoices

Send every paid invoice, including:
- Historical invoices (for accurate cohort analysis)
- Prorated invoices (GrowPanel handles proration)
- Zero-amount invoices (for trials converting to paid)

### Use cents for amounts

All amounts should be in the smallest currency unit:
- $99.00 → `9900`
- €49.50 → `4950`
- ¥1000 → `1000`

### Include period dates

`period_start` and `period_end` help GrowPanel:
- Handle partial-month invoices correctly
- Align billing cycles across customers
- Calculate accurate daily MRR

---

## API reference

For complete endpoint documentation:

- [Import Data API](/developers/rest-api/reference/data/) - Push customers, plans, and invoices
- [Customers endpoint](/developers/rest-api/reference/data/customers/) - CRUD operations for customers
- [Plans endpoint](/developers/rest-api/reference/data/plans/) - CRUD operations for plans
- [Invoices endpoint](/developers/rest-api/reference/data/invoices/) - CRUD operations for invoices

---

## Need help?

Building an integration and have questions?

- **Support:** Use the support widget or email hello@growpanel.io
- **Include:** Your use case, billing platform, and any specific questions

We're happy to help you connect your billing system to GrowPanel.

---

## CLI
<!-- url: https://growpanel.io/developers/cli -->

The GrowPanel CLI lets you access your subscription analytics, manage data, and configure settings directly from the terminal. It's designed for scripting, automation, and AI agents.

---

## Installation

Install globally via npm (requires Node.js 20 or later):

```bash
npm install -g growpanel-cli
```

Verify the installation:

```bash
growpanel --version
```

---

## Authentication

You need an API key from your GrowPanel dashboard. Go to **Settings > API Keys** and create one. See [Authentication](/developers/rest-api/authentication/) for details.

Configure the key using one of these methods (in priority order):

### CLI flag (highest priority)

```bash
growpanel --api-key YOUR_API_KEY reports summary
```

### Environment variable

```bash
export GROWPANEL_API_KEY=YOUR_API_KEY
```

### Config file

Create `~/.growpanelrc`:

```json
{
    "api_key": "YOUR_API_KEY"
}
```

---

## Quick start

```bash
# Get a summary of your key metrics
growpanel reports summary

# Get MRR timeline for 2024, broken down by month
growpanel reports mrr --date 20240101-20241231 --interval month

# List your customers
growpanel customers list

# Export all customers as CSV
growpanel exports customers > customers.csv
```

---

## Output formats

The CLI auto-detects the best format based on context:

- **Terminal** — Colored tables with formatted numbers
- **Piped or redirected** — Raw JSON for machine consumption

Override the default with `--format`:

```bash
growpanel reports summary --format json
growpanel reports summary --format table
growpanel reports summary --format csv
```

---

## Global options

These options work with any command:

| Option | Description |
|--------|-------------|
| `--api-key <key>` | API key (overrides env var and config file) |
| `--api-url <url>` | API base URL (default: `https://api.growpanel.io`) |
| `--format <fmt>` | Output format: `json`, `table`, or `csv` |
| `--no-color` | Disable colored output |
| `--verbose` | Log HTTP requests and responses to stderr |
| `--version` | Show version number |
| `--help` | Show help for any command |

---

## Reports

Fetch any subscription analytics report by name. New reports added to the API work automatically without a CLI update.

```bash
growpanel reports <name> [options]
```

### Report options

| Option | Description |
|--------|-------------|
| `--date <range>` | Date range in `yyyyMMdd-yyyyMMdd` format |
| `--interval <val>` | Aggregation: `day`, `week`, `month`, `quarter`, `year` |
| `--currency <code>` | Filter by currency code (e.g., `usd`, `eur`) |
| `--region <region>` | Filter by geographic region |
| `--plan <id>` | Filter by plan group ID |
| `--country <code>` | Filter by ISO country code |
| `--data-source <id>` | Filter by data source ID |
| `--breakdown <field>` | Group by: `plan`, `currency`, `billing_freq` |

### Available reports

`mrr`, `mrr-table`, `mrr-table-subtypes`, `summary`, `cmrr-summary`, `movement-table`, `map`, `cohort`, `leads`, `leads-table`, `leads-days`, `leads-summary`, `transactions`, `transactions-table`, `transactions-detail`, `transactions-summary`, `invoices-detail`, `churn-scheduled`, `churn-scheduled-movements`, `churn-scheduled-summary`, `customer-concentration`, `cashflow-failed-payments`, `cashflow-failed-payments-summary`, `cashflow-failed-payments-detail`, `cashflow-failed-payments-table`, `cashflow-refunds`, `cashflow-refunds-table`, `cashflow-refunds-detail`, `cashflow-failure-rate`, `cashflow-failure-rate-summary`, `cashflow-outstanding-unpaid`, `custom-variables`

### Examples

```bash
# MRR over the last year, grouped by month
growpanel reports mrr --date 20240101-20241231 --interval month

# Summary metrics as JSON
growpanel reports summary --format json

# Cohort retention filtered to USD customers
growpanel reports cohort --currency usd

# MRR broken down by plan
growpanel reports mrr --breakdown plan

# Failed payments for Q4
growpanel reports cashflow-failed-payments --date 20241001-20241231
```

---

## Customers

```bash
# List all customers
growpanel customers list
growpanel customers list --limit 50 --offset 100

# Get a specific customer
growpanel customers get cus_abc123

# Trigger a resync (admin/owner only)
growpanel customers resync cus_abc123
```

---

## Plans

```bash
growpanel plans list
```

---

## Data management

Generic CRUD operations for data resources. Supported resources: `customers`, `plans`, `plan-groups`, `data-sources`, `invoices`.

### Standard CRUD

```bash
growpanel data customers list
growpanel data customers get cus_abc123
growpanel data customers create --body '{"id":"cus_new","name":"Acme Inc","email":"billing@acme.com"}'
growpanel data customers update cus_abc123 --body '{"name":"Updated Name"}'
growpanel data customers delete cus_abc123
```

### Data source operations

```bash
growpanel data data-sources list
growpanel data data-sources reset ds_123
growpanel data data-sources connect ds_123
growpanel data data-sources full-import ds_123
growpanel data data-sources progress ds_123
growpanel data data-sources abort ds_123
```

### Plan group operations

```bash
growpanel data plan-groups list
growpanel data plan-groups ai-suggest --body '{"plans":["plan1","plan2"]}'
growpanel data plan-groups merge --body '{"source":"pg1","target":"pg2"}'
growpanel data plan-groups delete-multiple --body '{"ids":["pg1","pg2"]}'
```

---

## Exports

Export data as CSV. Output goes directly to stdout, so redirect to a file:

```bash
growpanel exports customers > customers.csv
growpanel exports mrr-movements > movements.csv
growpanel exports customers --date 20240101-20241231 > customers_2024.csv
```

---

## Settings

```bash
# Get all account settings
growpanel settings get

# Update settings
growpanel settings update --body '{"base_currency":"usd"}'

# Integration settings (GET without --body, update with --body)
growpanel settings notifications
growpanel settings notifications --body '{"email_reports":true}'
growpanel settings stripe
growpanel settings hubspot
growpanel settings webhook
growpanel settings slack
growpanel settings teams
growpanel settings looker-studio
```

---

## Integrations

Manage webhook subscriptions for third-party platforms like n8n or Zapier.

```bash
growpanel integrations verify
growpanel integrations webhooks list
growpanel integrations webhooks get wh_123
growpanel integrations webhooks create --body '{"url":"https://example.com/hook","events":["customer.created"]}'
growpanel integrations webhooks delete wh_123
growpanel integrations webhooks sample customer.created
```

---

## Account management

### Account

```bash
growpanel account get
growpanel account update --body '{"name":"New Account Name"}'
```

### Billing

```bash
growpanel account billing details
growpanel account billing invoices
growpanel account billing portal
growpanel account billing subscribe --body '{"plan":"pro"}'
growpanel account billing change-plan --body '{"plan":"enterprise"}'
growpanel account billing undo-cancellation
```

### Team

```bash
growpanel account team list
growpanel account team invite --body '{"email":"user@example.com","role":"admin"}'
growpanel account team edit user_123 --body '{"role":"readonly"}'
growpanel account team remove user_123
```

### API keys

```bash
growpanel account api-keys list
growpanel account api-keys create --body '{"name":"CI Key","role":"readonly"}'
growpanel account api-keys update key_123 --body '{"name":"Renamed"}'
growpanel account api-keys delete key_123
```

---

## Generic API passthrough

Call any API endpoint directly. Useful for new endpoints or one-off requests:

```bash
# GET with query parameters
growpanel api GET /reports/mrr date=20240101-20250131 interval=month

# POST with JSON body
growpanel api POST /data/customers --body '{"name":"Acme","email":"a@b.com"}'

# DELETE
growpanel api DELETE /data/customers/cus_123
```

---

## Request body input

Commands that accept a request body support three input methods:

```bash
# Inline JSON
growpanel data customers create --body '{"name":"Acme"}'

# From a file
growpanel data customers create --body @customer.json

# Piped from stdin
echo '{"name":"Acme"}' | growpanel data customers create
cat customer.json | growpanel data customers create
```

---

## Usage with AI agents

The CLI is optimized for AI agents and automation:

- JSON output by default when piped (no extra flags needed)
- Consistent error messages on stderr, data on stdout
- Exit code 0 on success, 1 on error
- All commands are non-interactive
- Detailed `--help` on every command
- New API endpoints work automatically via `growpanel api` passthrough

```bash
# AI agent workflow
export GROWPANEL_API_KEY=your-key

# Get structured data
growpanel reports summary --format json

# Chain with jq
growpanel reports mrr --format json | jq '.[0].total_mrr'

# Pipe CSV to other tools
growpanel exports customers | csvtool col 1,2 -
```

---

## Need help?

- Run `growpanel --help` or `growpanel <command> --help` for usage details
- Check the [API documentation](/developers/rest-api/) for endpoint specifics
- Review [Authentication](/developers/rest-api/authentication/) for API key setup
- Use the support widget for help

---

## Developers
<!-- url: https://growpanel.io/developers/ -->

Build integrations, access your data programmatically, and extend GrowPanel to fit your workflow.

> **Building an AI agent or integration?** The complete developer documentation is available as a single markdown file at **[growpanel.io/developers.md](/developers.md)** — ideal for feeding into Claude, ChatGPT, Cursor, or any other AI tool. See [AI agent reference](/docs/ai-reference/) for more.

---

## Build your own integration

Don't see your billing platform in our native integrations? You can connect any billing system to GrowPanel using our Import Data API.

**[Building integrations](/developers/building-integrations/)** - Learn how GrowPanel processes subscription data and how to push customers, plans, and invoices from any billing system.

This is the recommended starting point if you want to connect a custom billing system, in-house platform, or any service we don't natively integrate with.

---

## REST API

Access your subscription data and reports programmatically.

**[REST API documentation](/developers/rest-api/)** - Complete API reference including authentication, endpoints, and rate limits.

| Resource | Description |
|----------|-------------|
| [Authentication](/developers/rest-api/authentication/) | API keys and access levels |
| [API Reference](/developers/rest-api/reference/) | All endpoints for reports, data, customers, and settings |
| [Error codes](/developers/rest-api/error-codes/) | HTTP status codes and troubleshooting |
| [Rate limiting](/developers/rest-api/rate-limiting/) | Request limits and best practices |

### Quick example

```bash
curl https://api.growpanel.io/v1/reports/summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

---

## MCP Server

Let AI assistants access your GrowPanel data through natural language.

**[MCP Server documentation](/developers/mcp-server/)** - Connect Claude, Cursor, and other AI tools to your subscription analytics.

The MCP (Model Context Protocol) server runs locally and provides tools for querying:

| Tool | What you can ask |
|------|------------------|
| `getMRR` | MRR, ARR, churn, LTV, ARPA |
| `getLeads` | Leads, trials, conversion rates |
| `getCohorts` | Cohort retention analysis |

### Quick start

```bash
npm install -g growpanel-mcp-server
export GROWPANEL_API_TOKEN=sk_live_xxx
growpanel-mcp
```

---

## CLI

Access your subscription analytics and manage your account from the terminal. Designed for scripting, automation, and AI agents.

**[CLI documentation](/developers/cli/)** - Installation, authentication, and full command reference.

```bash
npm install -g growpanel-cli
growpanel reports summary
```

| Command | Description |
|---------|-------------|
| `reports <name>` | Fetch any analytics report (MRR, churn, cohort, etc.) |
| `customers` | List and query customers |
| `data <resource>` | CRUD for customers, plans, invoices, data sources |
| `exports` | Export data as CSV |
| `settings` | Manage account and integration settings |
| `api <method> <path>` | Raw API passthrough for any endpoint |

---

## Need help?

- Check the [API reference](/developers/rest-api/reference/) for endpoint details
- Review [error codes](/developers/rest-api/error-codes/) for troubleshooting
- Use the support widget for help

---

## MCP Server
<!-- url: https://growpanel.io/developers/mcp-server -->

The GrowPanel MCP Server lets AI assistants like Claude, Cursor, and other MCP-compatible tools access your subscription analytics through natural language.

---

## What is MCP?

MCP (Model Context Protocol) is an open standard that allows AI assistants to securely connect to external data sources. With the GrowPanel MCP Server, you can ask questions like "What's my current MRR?" or "Show me churn for the last quarter" directly in your AI assistant.

---

## Installation

### Prerequisites

- Node.js 18 or later (the server uses the global `fetch` API)
- A GrowPanel account with API access
- An MCP-compatible AI client (Claude Desktop, Cursor, etc.)

### Step 1: Install the server

Install the MCP server globally via npm:

```bash
npm install -g growpanel-mcp-server
```

### Step 2: Set your API token

Export your GrowPanel API token as an environment variable:

```bash
export GROWPANEL_API_TOKEN=sk_live_xxx
```

You can find your API token in GrowPanel under **Settings > API Keys**. See [Authentication](/developers/rest-api/authentication/) for details on creating API keys.

### Step 3: Start the server

Run the MCP server:

```bash
growpanel-mcp
```

The server starts on `http://localhost:3000/mcp` by default.

### Step 4: Connect your AI client

Configure your MCP client to connect to the server endpoint:

```
http://localhost:3000/mcp
```

Refer to your AI client's documentation for specific setup instructions.

---

## Available tools

The MCP server exposes three tools that your AI assistant can use:

| Tool | Description | Metrics included |
|------|-------------|------------------|
| `getMRR` | Revenue metrics | MRR, ARR, ARPA, ASP, churn rate, LTV |
| `getLeads` | Lead and trial metrics | Leads, trials, trial conversion rate |
| `getCohorts` | Cohort analysis | Revenue retention, logo retention by cohort |

### getMRR

Returns your key revenue metrics:

- **MRR** - Monthly Recurring Revenue
- **ARR** - Annual Recurring Revenue
- **ARPA** - Average Revenue Per Account
- **ASP** - Average Selling Price
- **Churn metrics** - Revenue churn rate, logo churn rate
- **LTV** - Customer Lifetime Value

### getLeads

Returns lead and trial funnel metrics:

- **Leads** - Total leads in period
- **Trials** - Active trials
- **Trial conversion** - Percentage of trials converting to paid

### getCohorts

Returns cohort analysis data for understanding retention patterns over time.

---

## Filtering data

All tools support the same query parameters as the GrowPanel API. Pass filters to narrow down your results:

| Filter | Format | Example |
|--------|--------|---------|
| `date` | `YYYYMMDD-YYYYMMDD` | `date=20240101-20240331` |
| `region` | Region code | `region=US` |
| `plan` | Plan ID | `plan=plan_pro` |

Example queries you might ask your AI assistant:

- "What was my MRR in Q1 2024?"
- "Show me churn metrics for the US region"
- "Get cohort retention for customers on the Pro plan"

---

## How it works

The MCP server runs locally on your machine and acts as a bridge between your AI assistant and the GrowPanel API:

1. Your AI assistant sends a natural language query
2. The MCP server translates this into the appropriate API call
3. The server authenticates using your Bearer token
4. Data is fetched from `https://api.growpanel.io`
5. Results are returned to your AI assistant in a structured format

Because the server runs locally, your API token never leaves your machine.

---

## Example usage

Once connected, you can ask your AI assistant questions like:

**Revenue questions:**
- "What's my current MRR?"
- "How has ARR changed over the last 6 months?"
- "What's my average revenue per account?"

**Churn questions:**
- "What's my churn rate this month?"
- "Show me LTV trends"

**Funnel questions:**
- "How many trials converted last month?"
- "What's my trial-to-paid conversion rate?"

**Cohort questions:**
- "Show me retention by signup cohort"
- "How does the January cohort compare to February?"

---

## Troubleshooting

### Server won't start

Ensure you have Node.js 18 or later:

```bash
node --version
```

### Authentication errors

Verify your API token is set correctly:

```bash
echo $GROWPANEL_API_TOKEN
```

The token should start with `sk_live_` or `sk_test_`.

### Connection refused

Make sure the server is running and your MCP client is configured to connect to `http://localhost:3000/mcp`.

---

## Security considerations

- The MCP server runs locally and only communicates with `https://api.growpanel.io`
- Your API token is stored in your local environment, not transmitted to third parties
- Use a read-only API key if you only need to query data
- Rotate your API key periodically for security

---

## Need help?

- Check the [API documentation](/developers/rest-api/) for details on available data
- Review [Authentication](/developers/rest-api/authentication/) for API key setup
- Use the support widget for help

---

## API Authentication
<!-- url: https://growpanel.io/developers/rest-api/authentication -->

All GrowPanel API requests require authentication using an API key.

---

## Obtain an API key

1. Click the account/profile menu in the upper right corner
2. Click **API Keys**
3. Click the **Create API key** button

See [API Keys](/docs/account-and-billing/api-keys/) for detailed instructions on managing your keys.

---

## Access levels

API keys can have different access levels:

| Level | Capabilities |
|-------|--------------|
| **admin** | Full access including settings, team management, and data modifications |
| **readonly** | Read-only access to reports and data |

---

## Store your key securely

After creation, the key is shown **once**. Copy it to a secure location:

- Password manager
- Secrets vault (AWS Secrets Manager, HashiCorp Vault)
- Encrypted environment variables

The key cannot be retrieved again. If you lose it, you'll need to regenerate or create a new key.

---

## Using the API key

GrowPanel uses Bearer Authentication. Include your API key in the `Authorization` HTTP header:

```bash
curl https://api.growpanel.io/v1/reports/mrr \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Example header format:

```
Authorization: Bearer xxxxxxxx-b4ad-4b05-xxxx-76ed42c6e692.xxxxxxxx-5ff6-4862-xxxx-a992a789ea60
```

---

## Related pages

- [API Keys management](/docs/account-and-billing/api-keys/) - Creating and managing keys
- [API Reference](/developers/rest-api/reference/) - Complete endpoint documentation
- [Error codes](/developers/rest-api/error-codes/) - Authentication errors

---

## API Error Codes
<!-- url: https://growpanel.io/developers/rest-api/error-codes -->

When an API call results in an error, GrowPanel returns an HTTP status code along with an error message.

---

## Error response format

```json
{
  "message": "Device parameter missing"
}
```

---

## HTTP status codes

| Status code | Description |
|-------------|-------------|
| 400 | Bad Request. Maybe you're missing some parameters |
| 401 | Unauthorized. Your API key may be invalid. |
| 403 | Forbidden. Your API key does not have access to the resource. |
| 404 | The resource was not found. |
| 405 | Method (GET, POST, PUT, DELETE) not allowed. |
| 429 | Too many requests. Your request has been [rate limited](/developers/rest-api/rate-limiting/) |
| 500 | Internal server error. If this error persists, get in touch with us. |
| 501-599 | A problem occurred connecting to the GrowPanel platform. Try again later. |

---

## Common errors and solutions

### 401 Unauthorized

**Cause:** Invalid or missing API key.

**Solution:**
1. Verify your API key is correct
2. Ensure the `Authorization: Bearer YOUR_API_KEY` header is included
3. Check if the key was regenerated or deleted

### 403 Forbidden

**Cause:** Your API key doesn't have permission for this resource.

**Solution:**
1. Verify the key has the correct access level (admin vs readonly)
2. Check if you're accessing resources from another account

### 429 Too Many Requests

**Cause:** Rate limit exceeded.

**Solution:**
1. Wait for the rate limit window to reset (usually 1 minute)
2. Implement exponential backoff in your integration
3. Reduce request frequency

See [Rate limiting](/developers/rest-api/rate-limiting/) for current limits.

---

## Related pages

- [Authentication](/developers/rest-api/authentication/) - Setting up API access
- [Rate limiting](/developers/rest-api/rate-limiting/) - Request limits
- [API Reference](/developers/rest-api/reference/) - Endpoint documentation

---

## REST API
<!-- url: https://growpanel.io/developers/rest-api/ -->

GrowPanel provides a REST API for programmatic access to your subscription data and reports.

**Base URL:** `https://api.growpanel.io`

---

## What you can do

| Use case | Endpoints |
|----------|-----------|
| **Pull metrics** | Fetch MRR, ARR, churn, cohorts, and other reports |
| **Build dashboards** | Get summary metrics for custom dashboard widgets |
| **Export data** | Retrieve customer lists and transaction history |
| **Push data** | Import customers, plans, and invoices from custom billing systems |
| **Automate workflows** | Trigger actions based on subscription events |

---

## Getting started

1. **[Authentication](/developers/rest-api/authentication/)** - Obtain and use API keys
2. **[API Reference](/developers/rest-api/reference/)** - Complete endpoint documentation
3. **[Error codes](/developers/rest-api/error-codes/)** - Understanding API responses
4. **[Rate limiting](/developers/rest-api/rate-limiting/)** - Request limits and best practices

---

## Quick example

Fetch your current MRR:

```bash
curl https://api.growpanel.io/v1/reports/summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Response:

```json
{
  "summary": {
    "mrr_current": 125000,
    "arr_current": 1500000,
    "subscribers_current": 250,
    "arpa_current": 500
  }
}
```

---

## Related

- [Building integrations](/developers/building-integrations/) - How to connect custom billing systems
- [Custom API data source](/docs/data-sources/custom-api/) - Step-by-step setup guide

---

## API Rate Limiting
<!-- url: https://growpanel.io/developers/rest-api/rate-limiting -->

To ensure a stable and reliable platform, the GrowPanel API applies rate limiting. When a client sends too many requests in a short period, the API responds with **HTTP 429 (Too Many Requests)**.

---

## Current limits

The API enforces the following per-account request limits:

| Method | Limit |
|--------|-------|
| **GET** | 300 requests per minute |
| **GET** (reports endpoints) | 30 requests per minute |
| **POST** | 100 requests per minute |
| **PUT** | 100 requests per minute |
| **DELETE** | 50 requests per minute |

These values may be adjusted over time as we optimize the platform.

---

## Rate limit response

When you exceed the limit, the API returns:

```
HTTP/1.1 429 Too Many Requests
```

```json
{
  "message": "Rate limit exceeded"
}
```

---

## Best practices

### Implement backoff

When you receive a 429 response, wait before retrying:

```javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);
    if (response.status !== 429) return response;

    const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
    await new Promise(resolve => setTimeout(resolve, waitTime));
  }
  throw new Error('Rate limit exceeded after retries');
}
```

### Batch requests

Where possible, use batch endpoints to reduce the number of API calls:

- Use date ranges to fetch multiple days of data in one request
- Use array parameters to filter for multiple items at once

### Cache responses

Cache API responses locally when the data doesn't change frequently:

- Summary metrics (cache for minutes)
- Customer lists (cache for hours)
- Historical reports (cache indefinitely)

---

## Need higher limits?

If you need higher rate limits for your use case, use the support widget and include:

- Your account email
- Description of your integration
- Expected request volume

---

## Related pages

- [Error codes](/developers/rest-api/error-codes/) - Understanding API errors
- [Authentication](/developers/rest-api/authentication/) - API key setup
- [API Reference](/developers/rest-api/reference/) - Endpoint documentation

---

## API Keys
<!-- url: https://growpanel.io/developers/rest-api/reference/account/api-keys -->

List and manage API keys for the authenticated account.

---

## GET /account/api-keys

Returns a list of all API keys (without the actual key values for security).

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/account/api-keys \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "result": {
    "count": 2,
    "list": [
      {
        "id": "key_001",
        "name": "Production integration",
        "access_level": "admin",
        "created_at": "2024-06-15T10:00:00Z",
        "last_used": "2025-01-10T08:45:00Z"
      },
      {
        "id": "key_002",
        "name": "Dashboard viewer",
        "access_level": "readonly",
        "created_at": "2024-09-01T14:30:00Z",
        "last_used": "2025-01-08T16:20:00Z"
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique key identifier |
| `name` | string | Descriptive name for the key |
| `access_level` | string | Permission level: admin or readonly |
| `created_at` | string | When the key was created |
| `last_used` | string | When the key was last used (null if never) |

---

## Notes

- API key values are not returned for security reasons
- To create, regenerate, or delete keys, use the GrowPanel web interface
- See [API Keys](/docs/account-and-billing/api-keys/) for management instructions

---

## Account Billing
<!-- url: https://growpanel.io/developers/rest-api/reference/account/billing -->

Retrieve billing and subscription information for the authenticated account.

---

## GET /account/billing

Returns the current plan, billing status, and usage information.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/account/billing \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "plan": "growth",
  "status": "active",
  "billing_cycle": "monthly",
  "current_period_start": "2025-01-01T00:00:00Z",
  "current_period_end": "2025-02-01T00:00:00Z",
  "mrr_limit": 500000,
  "current_mrr": 125000,
  "customer_limit": 1000,
  "current_customers": 250
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `plan` | string | Current subscription plan (free, starter, growth, scale) |
| `status` | string | Billing status (active, past_due, cancelled) |
| `billing_cycle` | string | Billing frequency (monthly, yearly) |
| `current_period_start` | string | Start of current billing period |
| `current_period_end` | string | End of current billing period |
| `mrr_limit` | integer | Maximum MRR allowed on current plan |
| `current_mrr` | integer | Current total MRR across all data sources |
| `customer_limit` | integer | Maximum customers allowed on current plan |
| `current_customers` | integer | Current total customer count |

---

## Account API
<!-- url: https://growpanel.io/developers/rest-api/reference/account/ -->

The **Account API** allows you to retrieve account settings, user profile, team members, and API keys.

---

## Endpoints

| Endpoint | Description |
|----------|-------------|
| [GET /account](/developers/rest-api/reference/account/profile/) | Get account information |
| [GET /profile](/developers/rest-api/reference/account/profile/) | Get user profile |
| [PUT /profile](/developers/rest-api/reference/account/profile/) | Update user profile |
| [GET /account/billing](/developers/rest-api/reference/account/billing/) | Get billing and subscription details |
| [GET /account/team](/developers/rest-api/reference/account/team/) | List team members |
| [GET /account/api-keys](/developers/rest-api/reference/account/api-keys/) | List API keys |

---

## Authentication

All Account API endpoints require an API key with **admin** access level.

```bash
curl https://api.growpanel.io/account \
  -H "Authorization: Bearer YOUR_API_KEY"
```

---

## Related pages

- [API Keys management](/docs/account-and-billing/api-keys/) - Creating keys in the UI
- [Team management](/docs/account-and-billing/team/) - Managing team members

---

## Account and Profile
<!-- url: https://growpanel.io/developers/rest-api/reference/account/profile -->

Retrieve account details or the logged-in user's profile.

---

## GET /account

Returns account information including name, currency, timezone, and data sources.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/account \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "id": "acc_123",
  "name": "Acme Corp",
  "base_currency": "usd",
  "timezone": "America/New_York",
  "first_day_of_week": 1,
  "data_sources": [
    {
      "id": "ds_001",
      "name": "Stripe",
      "type": "stripe"
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique account identifier |
| `name` | string | Account or company name |
| `base_currency` | string | Default reporting currency |
| `timezone` | string | Account timezone |
| `first_day_of_week` | integer | First day of the week (0 = Sunday, 1 = Monday) |
| `data_sources` | array | Connected data sources |

---

## GET /profile

Returns the logged-in user's profile and their account memberships.

### Authentication

Requires a valid API key or session.

```bash
curl https://api.growpanel.io/profile \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "first_name": "Jane",
  "last_name": "Smith",
  "email": "jane@acme.com",
  "locale": "en",
  "picture": "https://...",
  "provider": "google",
  "verified": true,
  "accounts": [
    {
      "id": "acc_123",
      "name": "Acme Corp",
      "role": "owner"
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `first_name` | string | User's first name |
| `last_name` | string | User's last name |
| `email` | string | User's email address |
| `locale` | string | Preferred locale |
| `picture` | string | Profile picture URL |
| `provider` | string | Authentication provider (google, microsoft, credentials) |
| `verified` | boolean | Whether the email is verified |
| `accounts` | array | List of accounts the user belongs to, with role |

---

## PUT /profile

Update the logged-in user's profile.

### Request

```bash
curl -X PUT https://api.growpanel.io/profile \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "locale": "en"
  }'
```

### Response

**Status:** 200 OK

Returns the updated profile object (same shape as GET /profile).

---

## Team Members
<!-- url: https://growpanel.io/developers/rest-api/reference/account/team -->

Retrieve team member information for the authenticated account.

---

## GET /account/team

Returns a list of all team members with their roles and status.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/account/team \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "result": {
    "count": 3,
    "list": [
      {
        "id": "usr_001",
        "email": "owner@acme.com",
        "name": "Jane Smith",
        "role": "owner",
        "status": "active",
        "last_login": "2025-01-10T14:30:00Z"
      },
      {
        "id": "usr_002",
        "email": "admin@acme.com",
        "name": "John Doe",
        "role": "admin",
        "status": "active",
        "last_login": "2025-01-09T09:15:00Z"
      },
      {
        "id": "usr_003",
        "email": "viewer@acme.com",
        "name": "Alex Johnson",
        "role": "readonly",
        "status": "pending",
        "last_login": null
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Unique user identifier |
| `email` | string | User's email address |
| `name` | string | User's display name |
| `role` | string | Permission level: owner, admin, or readonly |
| `status` | string | Account status: active, pending, or disabled |
| `last_login` | string | Last login timestamp (null if never logged in) |

---

## Related pages

- [Team management](/docs/account-and-billing/team/) - Managing team in the UI

---

## Failed payment detail
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-failed-payments-detail -->

The `/reports/cashflow-failed-payments-detail` endpoint returns individual failed payment records for a given period, with optional filtering by recovery status.

## GET /reports/cashflow-failed-payments-detail

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `selected-date` | string | Period start date to show failed payments for. Required. |
| `selected-type` | string | Filter by status: `still_unpaid`, `recovered`, or `churned`. |
| `baseCurrency` | string | Target currency for conversion. |
| `interval` | string | Aggregation interval. Defaults to `month`. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "result": {
    "list": [
      {
        "date": "2025-01-05",
        "invoice_ref": "in_failed_001",
        "customer_id": "cus_123",
        "customer_name": "Acme Corp",
        "customer_email": "billing@acme.com",
        "amount": 9900,
        "amount_base_currency": 9900,
        "currency": "usd",
        "payment_method": "card",
        "description": "Pro Plan - Jan 2025",
        "attempt_count": 3,
        "recovery_status": "recovered"
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Date of the failed payment |
| `invoice_ref` | string | Invoice reference ID |
| `customer_id` | string | Customer external ID |
| `customer_name` | string | Customer name |
| `customer_email` | string | Customer email |
| `amount` | number | Failed amount in original currency (cents) |
| `amount_base_currency` | number | Failed amount in base currency (cents) |
| `currency` | string | Original payment currency |
| `payment_method` | string | Payment method used |
| `description` | string | Payment description |
| `attempt_count` | integer | Number of payment attempts |
| `recovery_status` | string | Status: recovered, still_unpaid, or churned |

---

## Failed payments summary
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-failed-payments-summary -->

The `/reports/cashflow-failed-payments-summary` endpoint returns failed payment totals for month-to-date and year-to-date periods with comparisons to the prior equivalent periods, including recovery rates and failure percentages.

## GET /reports/cashflow-failed-payments-summary

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `fix_fx` | boolean | Use fixed exchange rates. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "summary": {
    "mtd_still_unpaid": 3000,
    "prev_mtd_still_unpaid": 4500,
    "ytd_still_unpaid": 15000,
    "prev_ytd_still_unpaid": 18000,
    "mtd_recovery_rate": 75.0,
    "prev_mtd_recovery_rate": 68.0,
    "ytd_recovery_rate": 72.5,
    "prev_ytd_recovery_rate": 65.0,
    "mtd_failed_pct": 3.2,
    "prev_mtd_failed_pct": 4.1,
    "ytd_failed_pct": 3.5,
    "prev_ytd_failed_pct": 4.0,
    "mtd_failed_invoices": 8,
    "prev_mtd_failed_invoices": 12,
    "ytd_failed_invoices": 45,
    "prev_ytd_failed_invoices": 55,
    "mtd_still_unpaid_change_pct": -33.3,
    "ytd_still_unpaid_change_pct": -16.7,
    "mtd_recovery_rate_change": 7.0,
    "ytd_recovery_rate_change": 7.5,
    "mtd_failed_pct_change": -0.9,
    "ytd_failed_pct_change": -0.5
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `mtd_still_unpaid` | number | Month-to-date unpaid amount (cents) |
| `prev_mtd_still_unpaid` | number | Previous month equivalent (cents) |
| `ytd_still_unpaid` | number | Year-to-date unpaid amount (cents) |
| `prev_ytd_still_unpaid` | number | Previous year equivalent (cents) |
| `mtd_recovery_rate` | float | Month-to-date recovery rate (%) |
| `prev_mtd_recovery_rate` | float | Previous month recovery rate (%) |
| `ytd_recovery_rate` | float | Year-to-date recovery rate (%) |
| `prev_ytd_recovery_rate` | float | Previous year recovery rate (%) |
| `mtd_failed_pct` | float | Month-to-date failure percentage |
| `prev_mtd_failed_pct` | float | Previous month failure percentage |
| `ytd_failed_pct` | float | Year-to-date failure percentage |
| `prev_ytd_failed_pct` | float | Previous year failure percentage |
| `mtd_failed_invoices` | integer | Month-to-date failed invoice count |
| `prev_mtd_failed_invoices` | integer | Previous month failed invoice count |
| `ytd_failed_invoices` | integer | Year-to-date failed invoice count |
| `prev_ytd_failed_invoices` | integer | Previous year failed invoice count |
| `*_change_pct` | float | Percentage change vs prior period |
| `*_change` | float | Absolute change vs prior period |

---

## Failed payments
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-failed-payments -->

The `/reports/cashflow-failed-payments` endpoint returns a timeline of failed payment metrics, including amounts failed, recovered, still unpaid, and churned, along with recovery rates.

## GET /reports/cashflow-failed-payments

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `date` | string | Date range. Format: `YYYYMMDD-YYYYMMDD`. Defaults to last 365 days. |
| `interval` | string | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `industry` | string | Filter by industry (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "result": [
    {
      "date": "2025-01-01",
      "failed_amount": 15000,
      "recovered": 10000,
      "still_unpaid": 3000,
      "churned": 2000,
      "failed_invoices": 12,
      "recovered_customers": 8,
      "still_unpaid_customers": 2,
      "churned_customers": 2,
      "affected_customers": 10,
      "total_invoices": 250,
      "failed_pct": 4.8,
      "recovery_rate": 66.7
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Period start date |
| `failed_amount` | number | Total failed payment amount (cents) |
| `recovered` | number | Amount recovered after retry (cents) |
| `still_unpaid` | number | Amount still outstanding (cents) |
| `churned` | number | Amount lost to churn (cents) |
| `failed_invoices` | integer | Number of failed invoices |
| `recovered_customers` | integer | Customers whose payments were recovered |
| `still_unpaid_customers` | integer | Customers still unpaid |
| `churned_customers` | integer | Customers who churned due to failed payment |
| `affected_customers` | integer | Total customers affected |
| `total_invoices` | integer | Total invoices in period |
| `failed_pct` | float | Percentage of invoices that failed |
| `recovery_rate` | float | Percentage of failed amount recovered |

---

## Failure rate summary
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-failure-rate-summary -->

The `/reports/cashflow-failure-rate-summary` endpoint returns failure rate and recovery rate for month-to-date and year-to-date periods with comparisons to prior equivalent periods.

## GET /reports/cashflow-failure-rate-summary

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `fix_fx` | boolean | Use fixed exchange rates. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "summary": {
    "mtd_failed_pct": 3.2,
    "prev_mtd_failed_pct": 4.1,
    "ytd_failed_pct": 3.5,
    "prev_ytd_failed_pct": 4.0,
    "mtd_recovery_rate": 75.0,
    "prev_mtd_recovery_rate": 68.0,
    "ytd_recovery_rate": 72.5,
    "prev_ytd_recovery_rate": 65.0,
    "mtd_failed_invoices": 8,
    "prev_mtd_failed_invoices": 12,
    "ytd_failed_invoices": 45,
    "prev_ytd_failed_invoices": 55,
    "mtd_failed_pct_change": -0.9,
    "ytd_failed_pct_change": -0.5,
    "mtd_recovery_rate_change": 7.0,
    "ytd_recovery_rate_change": 7.5
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `mtd_failed_pct` | float | Month-to-date failure percentage |
| `prev_mtd_failed_pct` | float | Previous month failure percentage |
| `ytd_failed_pct` | float | Year-to-date failure percentage |
| `prev_ytd_failed_pct` | float | Previous year failure percentage |
| `mtd_recovery_rate` | float | Month-to-date recovery rate (%) |
| `prev_mtd_recovery_rate` | float | Previous month recovery rate (%) |
| `ytd_recovery_rate` | float | Year-to-date recovery rate (%) |
| `prev_ytd_recovery_rate` | float | Previous year recovery rate (%) |
| `mtd_failed_invoices` | integer | Month-to-date failed invoice count |
| `prev_mtd_failed_invoices` | integer | Previous month failed invoice count |
| `ytd_failed_invoices` | integer | Year-to-date failed invoice count |
| `prev_ytd_failed_invoices` | integer | Previous year failed invoice count |
| `*_change` | float | Absolute change vs prior period |

---

## Payment failure rate
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-failure-rate -->

The `/reports/cashflow-failure-rate` endpoint returns payment failure rate and recovery rate metrics over time. Supports optional breakdown by dimension.

## GET /reports/cashflow-failure-rate

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `date` | string | Date range. Format: `YYYYMMDD-YYYYMMDD`. Defaults to last 365 days. |
| `interval` | string | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `breakdown` | string | Optional breakdown dimension. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "result": [
    {
      "date": "2025-01-01",
      "failed_pct": 3.2,
      "recovery_rate": 75.0,
      "failed_invoices": 8,
      "total_invoices": 250,
      "recovered_invoices": 6
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Period start date |
| `failed_pct` | float | Percentage of invoices that failed |
| `recovery_rate` | float | Percentage of failed payments recovered |
| `failed_invoices` | integer | Number of failed invoices |
| `total_invoices` | integer | Total invoices in period |
| `recovered_invoices` | integer | Number of recovered invoices |

When using the `breakdown` parameter, the response includes a `breakdown` object with per-dimension values.

---

## Outstanding unpaid
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-outstanding-unpaid -->

The `/reports/cashflow-outstanding-unpaid` endpoint returns the current outstanding unpaid invoice amount and how it has changed over time (30, 60, 180, 365 days).

## GET /reports/cashflow-outstanding-unpaid

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "outstanding": {
    "today": 25000,
    "d30": 22000,
    "d60": 20000,
    "d180": 15000,
    "d365": 10000,
    "invoice_count": 15,
    "change_d30": 3000,
    "change_d60": 5000,
    "change_d180": 10000,
    "change_d365": 15000,
    "change_pct_d30": 13.6,
    "change_pct_d60": 25.0,
    "change_pct_d180": 66.7,
    "change_pct_d365": 150.0
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `today` | number | Current outstanding unpaid amount (cents) |
| `d30` | number | Outstanding amount 30 days ago (cents) |
| `d60` | number | Outstanding amount 60 days ago (cents) |
| `d180` | number | Outstanding amount 180 days ago (cents) |
| `d365` | number | Outstanding amount 365 days ago (cents) |
| `invoice_count` | integer | Number of outstanding invoices |
| `change_d30` | number | Absolute change vs 30 days ago (cents) |
| `change_d60` | number | Absolute change vs 60 days ago (cents) |
| `change_d180` | number | Absolute change vs 180 days ago (cents) |
| `change_d365` | number | Absolute change vs 365 days ago (cents) |
| `change_pct_d30` | float | Percentage change vs 30 days ago |
| `change_pct_d60` | float | Percentage change vs 60 days ago |
| `change_pct_d180` | float | Percentage change vs 180 days ago |
| `change_pct_d365` | float | Percentage change vs 365 days ago |

---

## Refund detail
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-refunds-detail -->

The `/reports/cashflow-refunds-detail` endpoint returns individual refund records for a given period.

## GET /reports/cashflow-refunds-detail

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `selected-date` | string | Period start date to show refunds for. Required. |
| `baseCurrency` | string | Target currency for conversion. |
| `interval` | string | Aggregation interval. Defaults to `month`. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "result": {
    "list": [
      {
        "date": "2025-01-10",
        "invoice_ref": "in_refund_001",
        "customer_id": "cus_123",
        "customer_name": "Acme Corp",
        "customer_email": "billing@acme.com",
        "amount": 4900,
        "amount_base_currency": 4900,
        "currency": "usd",
        "payment_method": "card",
        "description": "Refund - Pro Plan"
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Refund date |
| `invoice_ref` | string | Invoice reference ID |
| `customer_id` | string | Customer external ID |
| `customer_name` | string | Customer name |
| `customer_email` | string | Customer email |
| `amount` | number | Refund amount in original currency (cents) |
| `amount_base_currency` | number | Refund amount in base currency (cents) |
| `currency` | string | Original payment currency |
| `payment_method` | string | Payment method |
| `description` | string | Refund description |

---

## Refunds
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/cashflow-refunds -->

The `/reports/cashflow-refunds` endpoint returns a timeline of refund metrics.

## GET /reports/cashflow-refunds

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `date` | string | Date range. Format: `YYYYMMDD-YYYYMMDD`. Defaults to last 365 days. |
| `interval` | string | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "result": [
    {
      "date": "2025-01-01",
      "refund_count": 5,
      "refund_amount": 12500,
      "customers_refunded": 4
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Period start date |
| `refund_count` | integer | Number of refunds issued |
| `refund_amount` | number | Total refund amount (cents) |
| `customers_refunded` | integer | Number of customers who received refunds |

---

## Cashflow reports
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/ -->

Endpoints for **transaction**, **cashflow**, **failed payment**, and **refund** reports.

---

## Transactions

| Endpoint | Description |
|----------|-------------|
| [GET /reports/transactions](/developers/rest-api/reference/cashflow/transactions/) | Transaction timeline by type |
| [GET /reports/transactions-detail](/developers/rest-api/reference/cashflow/transactions-detail/) | Individual transaction records |
| [GET /reports/transactions-summary](/developers/rest-api/reference/cashflow/transactions-summary/) | Transaction period summaries |
| [GET /reports/invoices-detail](/developers/rest-api/reference/cashflow/invoices-detail/) | Invoice detail with line items |

## Failed payments

| Endpoint | Description |
|----------|-------------|
| [GET /reports/cashflow-failed-payments](/developers/rest-api/reference/cashflow/cashflow-failed-payments/) | Failed payment timeline |
| [GET /reports/cashflow-failed-payments-detail](/developers/rest-api/reference/cashflow/cashflow-failed-payments-detail/) | Individual failed payment records |
| [GET /reports/cashflow-failed-payments-summary](/developers/rest-api/reference/cashflow/cashflow-failed-payments-summary/) | Failed payments summary |

## Refunds

| Endpoint | Description |
|----------|-------------|
| [GET /reports/cashflow-refunds](/developers/rest-api/reference/cashflow/cashflow-refunds/) | Refund timeline |
| [GET /reports/cashflow-refunds-detail](/developers/rest-api/reference/cashflow/cashflow-refunds-detail/) | Individual refund records |

## Failure rate & outstanding

| Endpoint | Description |
|----------|-------------|
| [GET /reports/cashflow-failure-rate](/developers/rest-api/reference/cashflow/cashflow-failure-rate/) | Payment failure rate timeline |
| [GET /reports/cashflow-failure-rate-summary](/developers/rest-api/reference/cashflow/cashflow-failure-rate-summary/) | Failure rate summary |
| [GET /reports/cashflow-outstanding-unpaid](/developers/rest-api/reference/cashflow/cashflow-outstanding-unpaid/) | Outstanding unpaid invoices |

---

## Invoice detail
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/invoices-detail -->

The `/reports/invoices-detail` endpoint returns detailed invoice records for a specific customer, including line items and payment information.

## GET /reports/invoices-detail

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `customer` | string | Customer external ID to retrieve invoices for. |
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |

### Example response

```json
200 OK
{
  "result": {
    "list": [
      {
        "invoice_ref": "in_abc123",
        "invoice_number": "INV-2025-001",
        "invoice_date": "2025-01-01",
        "invoice_status": "paid",
        "payment_date": "2025-01-01",
        "customer_id": "cus_123",
        "customer_name": "Acme Corp",
        "customer_email": "billing@acme.com",
        "description": "Pro Plan",
        "currency": "usd",
        "total": 9900,
        "total_base_currency": 9900,
        "transaction_count": 1,
        "lines": [
          {
            "description": "Pro Plan - Monthly",
            "amount": 9900,
            "quantity": 1,
            "period_start": "2025-01-01",
            "period_end": "2025-02-01"
          }
        ]
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `invoice_ref` | string | Invoice reference ID from billing source |
| `invoice_number` | string | Invoice number |
| `invoice_date` | string | Invoice date |
| `invoice_status` | string | Payment status |
| `payment_date` | string | Date payment was received |
| `customer_id` | string | Customer external ID |
| `customer_name` | string | Customer name |
| `customer_email` | string | Customer email |
| `description` | string | Invoice description |
| `currency` | string | Original invoice currency |
| `total` | number | Total in original currency (cents) |
| `total_base_currency` | number | Total in base currency (cents) |
| `transaction_count` | integer | Number of transactions on invoice |
| `lines` | array | Invoice line items |

---

## Transaction detail
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/transactions-detail -->

The `/reports/transactions-detail` endpoint returns individual transaction records for a given period and type. Use this to drill down into specific transaction categories from the [transactions](/developers/rest-api/reference/cashflow/transactions/) overview.

## GET /reports/transactions-detail

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `selected-date` | string | Period start date to show transactions for. *Not required when using `customer` parameter. |
| `selected-type` | string | Transaction type: `month_sub`, `year_sub`, `week_sub`, `day_sub`, `one_time`, `metered`, `discount`, `refund`, `fee`. *Not required when using `customer` parameter. |
| `customer` | string | Filter by customer ID. When set, shows transactions grouped by transaction. |
| `baseCurrency` | string | Target currency for conversion. |
| `interval` | string | Aggregation interval. Defaults to `month`. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "result": {
    "list": [
      {
        "date": "2025-01-15",
        "customer_id": "cus_123",
        "customer_name": "Acme Corp",
        "customer_email": "billing@acme.com",
        "type": "month_sub",
        "status": "paid",
        "transaction_id": "txn_abc123",
        "currency": "usd",
        "description": "Pro Plan - Jan 2025",
        "amount": 9900,
        "amount_base_currency": 9900
      }
    ]
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Transaction date |
| `customer_id` | string | Customer external ID |
| `customer_name` | string | Customer name |
| `customer_email` | string | Customer email |
| `type` | string | Transaction type |
| `status` | string | Payment status |
| `transaction_id` | string | Transaction reference ID |
| `currency` | string | Original transaction currency |
| `description` | string | Transaction description |
| `amount` | number | Amount in original currency (cents) |
| `amount_base_currency` | number | Amount in base currency (cents) |

When using the `customer` parameter, each transaction may include a `lines` array with invoice line-level detail.

---

## Transactions summary
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/transactions-summary -->

The `/reports/transactions-summary` endpoint returns transaction totals for month-to-date, quarter-to-date, and year-to-date periods with comparisons to the prior equivalent periods.

## GET /reports/transactions-summary

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `fix_fx` | boolean | Use fixed exchange rates. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `industry` | string | Filter by industry (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "summary": {
    "mtd": 95000,
    "prev_mtd": 88000,
    "qtd": 280000,
    "prev_qtd": 260000,
    "ytd": 520000,
    "prev_ytd": 480000,
    "mtd_change_pct": 7.95,
    "qtd_change_pct": 7.69,
    "ytd_change_pct": 8.33
  }
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `currency` | string | Reporting currency |
| `mtd` | number | Month-to-date net transactions (cents) |
| `prev_mtd` | number | Previous month's equivalent period (cents) |
| `qtd` | number | Quarter-to-date net transactions (cents) |
| `prev_qtd` | number | Previous quarter's equivalent period (cents) |
| `ytd` | number | Year-to-date net transactions (cents) |
| `prev_ytd` | number | Previous year's equivalent period (cents) |
| `mtd_change_pct` | float | Month-to-date percentage change vs prior |
| `qtd_change_pct` | float | Quarter-to-date percentage change vs prior |
| `ytd_change_pct` | float | Year-to-date percentage change vs prior |

---

## Transactions
<!-- url: https://growpanel.io/developers/rest-api/reference/cashflow/transactions -->

The `/reports/transactions` endpoint returns a timeline of transaction amounts broken down by type (monthly subscriptions, yearly subscriptions, one-time charges, metered usage, discounts, refunds, fees, tax, and net amount).

## GET /reports/transactions

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `date` | string | Date range. Format: `YYYYMMDD-YYYYMMDD`. Defaults to last 365 days. |
| `interval` | string | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency` | string | Target currency for conversion. Defaults to account base currency. |
| `fix_fx` | boolean | Use fixed exchange rates from start date. |
| `region` | string | Filter by region or country codes (space-separated). |
| `currency` | string | Filter by currency codes (space-separated). |
| `plan` | string | Filter by plan group IDs (space-separated). |
| `industry` | string | Filter by industry (space-separated). |
| `channel` | string | Filter by channel (space-separated). |
| `size` | string | Filter by customer size (space-separated). |
| `data_source` | string | Filter by data source ID (space-separated). |

### Example response

```json
200 OK
{
  "currency": "usd",
  "result": [
    {
      "date": "2025-01-01",
      "month_sub": 85000,
      "year_sub": 35000,
      "week_sub": 0,
      "day_sub": 0,
      "one_time": 5000,
      "metered": 2000,
      "discount": -3000,
      "refund": -1500,
      "fee": -2500,
      "fx_loss": -200,
      "tax": 8000,
      "net_amount": 127800,
      "net_amount_change_pct": 4.2
    }
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Period start date |
| `month_sub` | number | Monthly subscription revenue (cents) |
| `year_sub` | number | Yearly subscription revenue (cents) |
| `week_sub` | number | Weekly subscription revenue (cents) |
| `day_sub` | number | Daily subscription revenue (cents) |
| `one_time` | number | One-time charges (cents) |
| `metered` | number | Metered/usage-based revenue (cents) |
| `discount` | number | Discounts applied (cents, negative) |
| `refund` | number | Refunds issued (cents, negative) |
| `fee` | number | Fees deducted (cents, negative) |
| `fx_loss` | number | Foreign exchange loss (cents, negative) |
| `tax` | number | Tax collected (cents) |
| `net_amount` | number | Net transaction amount (cents) |
| `net_amount_change_pct` | float | Percentage change vs previous period |

---

## Customers
<!-- url: https://growpanel.io/developers/rest-api/reference/customers/ -->

The **Customers API** allows you to **list and retrieve detailed information about your customers**. You can filter, sort, and convert MRR to a base currency when listing customers.

---

## List customers

**Endpoint:** `GET /customers`

Fetch a list of customers for your account, with optional filters and sorting.

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `limit` | integer | Maximum number of customers to return. |
| `status` | string | Filter by customer status. Values: `active`, `cancelled`, `all`. Defaults to `active`. |
| `q` | string | Search by customer name, email, or external ID (partial match). |
| `region` | string | Space-separated region names or country codes. |
| `currency` | string | Space-separated currency codes to filter customers. |
| `industry` | string | Space-separated industries. |
| `channel` | string | Space-separated channels. |
| `size` | string | Space-separated customer sizes. |
| `selected-date` | string | Date to filter by creation, trial, or conversion. Format: `YYYY-MM-DD`. |
| `selected-type` | string | Type for date filter: `lead`, `trials`, or `converted`. Defaults to `lead`. |
| `interval` | string | Interval for `selected-date` filter: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency` | string | Convert all MRR values to this currency. Defaults to the account's base currency. |
| `sort` | string | Field to sort by: `created_date`, `mrr`, `total_paid`, `country`, `paid_started`, `cancel_date`, `trial_started`, `status`. |
| `order` | string | Sort order: `asc` or `desc`. Defaults to descending by MRR. |

### Response

```json
{
  "result": {
    "count": 2,
    "list": [
      {
        "id": "cus_123",
        "name": "Acme Inc",
        "email": "contact@acme.com",
        "created_date": "2024-01-15",
        "country": "US",
        "mrr": 5000,
        "trial_started": "2024-01-10",
        "paid_started": "2024-01-15",
        "cancel_date": null,
        "status": "active",
        "currency": "usd",
        "total_paid_customer_currency": 24500,
        "total_paid_base_currency": 24500
      }
    ]
  }
}
````

---

## Get customer details

**Endpoint:** `GET /customers/{customerId}`

Retrieve full details for a single customer, including current subscriptions and MRR converted to a base currency.

### Path parameters

| Parameter    | Type   | Description                  |
| ------------ | ------ | ---------------------------- |
| `customerId` | string | External ID of the customer. |

### Query parameters

| Parameter      | Type   | Description                                                             |
| -------------- | ------ | ----------------------------------------------------------------------- |
| `baseCurrency` | string | Convert MRR values to this currency. Defaults to account base currency. |

### Response

```json
{
  "id": "cus_123",
  "name": "Acme Inc",
  "email": "contact@acme.com",
  "created_date": "2024-01-15",
  "country": "US",
  "status": "active",
  "currency": "usd",
  "trial_started": "2024-01-10",
  "paid_started": "2024-01-15",
  "cancel_date": null,
  "total_paid": {"usd": 24500},
  "converted_total_paid": 24500,
  "current_subscriptions": [
    {
      "plan_id": "plan_001",
      "name": "Pro Plan",
      "billing_freq": "month",
      "billing_freq_count": 1,
      "currency": "usd",
      "mrr": 5000
    }
  ],
  "converted_mrr": 5000
}
```

---

## Resync customer

**Endpoint:** `POST /customers/{customerId}/resync`

Triggers a resync of a single customer from the original billing source. This re-imports the customer's data and recalculates their metrics.

### Authentication

Requires an API key with **admin** access level.

### Path parameters

| Parameter    | Type   | Description                  |
| ------------ | ------ | ---------------------------- |
| `customerId` | string | External ID of the customer. |

### Response

**Status:** 200 OK

```json
{
  "message": "Resync initiated"
}
```

---

## Notes

* `current_subscriptions` contains all subscriptions active for the customer.
* `converted_mrr` reflects MRR in the selected `baseCurrency`, calculated using the latest exchange rates.
* Use filters and sorting to efficiently query large customer datasets.

---

## Customers
<!-- url: https://growpanel.io/developers/rest-api/reference/data/customers -->

The `/data/customers` endpoint provides full CRUD operations for raw customer records. This endpoint focuses on the **raw fields of customers** (name, email, country, currency, status, trial and paid dates) and is intended for **import/export and bulk operations**, not derived metrics like MRR or subscription status.

---

## List customers

Retrieve all customer records for the authenticated account.

**Request**

```

GET /data/customers

````

**Query parameters**

| Parameter | Type   | Required | Description |
|-----------|--------|----------|-------------|
| `limit`  | number | No       | Maximum number of records to return. |

**Response**

**Status:** 200 OK  

```json
{
  "result": {
    "count": 2,
    "list": [
      {
        "id": "cus_123",
        "name": "Acme Corp",
        "email": "admin@acme.com",
        "created_date": "2025-10-01T12:00:00.000Z",
        "country": "US",
        "trial_started": "2025-09-01T12:00:00.000Z",
        "paid_started": "2025-09-15T12:00:00.000Z",
        "cancel_date": null,
        "status": "active",
        "currency": "USD",
        "data_source": "xxxx-aaaa-bbb"
      }
    ]
  }
}
````

---

## Retrieve single customer

```
GET /data/customers/{id}
```

**Response**

```json
{
    "id": "cus_456",
    "name": "Beta LLC",
    "email": "contact@beta.com",
    "country": "US",
    "currency": "usd",
    "status": "active",
    "trial_started": "2025-10-01T00:00:00Z",
    "paid_started": "2025-10-15T00:00:00Z",
    "cancel_date": null,
    "created_date": "2025-10-01T12:00:00.000Z",
    "trial_end_date": "2025-04-08T20:52:41.000Z",
    "overdue_date": null,
    "custom_variables": {
        "owner": "Matt",
        "channel": "google-ads"
    },
    "status": "active",
    "data_source": "xxxbbbaa-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "cancel_reason": null,
    "current_mrr": {
        "usd": 4900
    }
}
```

---

## Create customer + bulk insert

Create one or multiple customer records. To **bulk insert**, provide an array of customer objects in the request body.

**Request**

```
POST /data/customers
Content-Type: application/json
```

**Body (single)**

```json
{
  "id": "cus_456",
  "name": "Beta LLC",
  "email": "contact@beta.com",
  "created_date": "2025-10-01T00:00:00Z",
  "country": "US",
  "trial_started": "2025-10-01T00:00:00Z",
  "data_source": "xxxx-aaaa-bbb"
}
```

**Body (bulk)**

```json
[
  {
    "id": "cus_456",
    "name": "Beta LLC",
    "email": "contact@beta.com",
    "created_date": "2025-10-01T00:00:00Z",
    "country": "US",
    "data_source": "xxxx-aaaa-bbb"
  },
  {
    "id": "cus_789",
    "name": "Gamma Inc",
    "email": "hello@gamma.com",
    "created_date": "2025-10-01T00:00:00Z",
    "country": "GB",
    "trial_started": "2025-10-01T00:00:00Z",
    "data_source": "xxxx-aaaa-bbb"
  }
]
```

**Response**

**Status:** 201 Created

```json
{
  "result": {
    "count": 2,
    "list": [
      { "id": "cus_456" },
      { "id": "cus_789" }
    ]
  }
}
```

---

## Update customer

Update an existing customer by ID. Only the fields included will be updated, the rest will be kept as they are.

The `custom_variables` object works the same way, and will be merged with the existing ones (the new ones taking precedence).

```
PUT /data/customers/{id}
Content-Type: application/json
```

**Body**

```json
{
    "name": "Beta LLC Updated",
    "email": "contact-new@beta.com",
    "custom_variables": {
        "owner": "John",
        "channel": "paid-ads"
    }
}
```

**Response**

**Status:** 200 OK

```json
{
    "success": true,
    "result": {
        "id": "cus_456",
        "name": "Beta LLC Updated",
        "email": "contact-new@beta.com",
        "country": "US",
        "currency": "usd",    
        "status": "active",
        "trial_started": "2025-10-01T00:00:00Z",
        "paid_started": "2025-10-15T00:00:00Z",
        "cancel_date": null,
        "created_date": "2025-10-01T12:00:00.000Z",
        "trial_end_date": "2025-04-08T20:52:41.000Z",
        "overdue_date": null,
        "custom_variables": {
            "owner": "Matt",
            "channel": "google-ads",
            "billing-id": "dcksdfkjn34"
        },
        "status": "active",
        "data_source": "xxxbbbaa-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "cancel_reason": null,
        "current_mrr": {
            "usd": 4900
        }
    }
}
```

---

## Delete customer

Delete a customer by ID.

```
DELETE /data/customers/{id}
```

**Response**

**Status:** 200 OK

```json
{
    "success": true,
    "id": "cus_456"
}
```

---

## Data sources
<!-- url: https://growpanel.io/developers/rest-api/reference/data/data-sources -->

Manage the data sources connected to your account. Each data source represents a system from which GrowPanel can import metrics (Stripe, CSV, Google Sheets, etc.).

**Base URL:** `/data/data-sources`

---

## List data sources

**GET** `/data/data-sources`

**Query parameters:**

| Parameter | Type   | Description                                                                                |
| --------- | ------ | ------------------------------------------------------------------------------------------ |
| `type`    | string | Optional. Filter by type (`stripe`, `api`, `csv`, `google-sheets`, `recurly`, `chargebee`) |

**Response:**

```json
{
  "result": [
    {
      "id": "uuid",
      "account_id": "your_account_id",
      "name": "Stripe",
      "type": "stripe",
      "created_at": "2025-10-02T12:00:00Z"
    }
  ]
}
```

---

## Create a new data source

**POST** `/data/data-sources`

**Body parameters:**

| Parameter | Type   | Description                                                                        |
| --------- | ------ | ---------------------------------------------------------------------------------- |
| `name`    | string | Required. Name of the data source.                                                 |
| `type`    | string | Required. One of: `stripe`, `api`, `csv`, `google-sheets`, `recurly`, `chargebee`. |

**Example request:**

```json
{
  "name": "Data from legacy system",
  "type": "google-sheets"
}
```

**Response (201 Created):**

```json
{
  "id": "2f7a9e3e-4f6d-4a3c-8b2a-0f1b4e7d8c9a",
  "account_id": "your_account_id",
  "name": "Data from legacy system",
  "type": "google-sheets",
  "created_at": "2025-10-02T12:00:00Z"
}
```

---

## Update a data source

**PUT** `/data/data-sources/:id`

**Path parameters:**

| Parameter | Type   | Description                                      |
| --------- | ------ | ------------------------------------------------ |
| `id`      | string | Required. The UUID of the data source to update. |

**Body parameters:** (only fields that need updating)

| Parameter | Type   | Description                                                                           |
| --------- | ------ | ------------------------------------------------------------------------------------- |
| `name`    | string | Optional. New name for the data source.                                               |
| `type`    | string | Optional. New type (`stripe`, `api`, `csv`, `google-sheets`, `recurly`, `chargebee`). |

**Example request:**

```json
{
  "name": "Stripe Sandbox",
  "type": "stripe"
}
```

**Response (200 OK):**

```json
{
  "id": "2f7a9e3e-4f6d-4a3c-8b2a-0f1b4e7d8c9a",
  "account_id": "your_account_id",
  "name": "Stripe Sandbox",
  "type": "stripe",
  "created_at": "2025-10-02T12:00:00Z"
}
```

---

## Delete a data source

**DELETE** `/data/data-sources/:id`

**Path parameters:**

| Parameter | Type   | Description                                      |
| --------- | ------ | ------------------------------------------------ |
| `id`      | string | Required. The UUID of the data source to delete. |

**Response (204 No Content):**

Deletes the data source. Returns no body.

---

## Import Data API
<!-- url: https://growpanel.io/developers/rest-api/reference/data/ -->

The **Import Data API** allows you to bring external data into GrowPanel so the system can build full MRR and transaction reports. You can import **customers**, **plans**, **invoices**, and **plan groups** from your external sources, such as Stripe, Braintree, or other billing platforms.

Imported data is used to:

- Calculate **MRR**, **ARR**, and other subscription metrics.
- Track **customer movements**: new, expansion, contraction, churn, and reactivation.
- Generate detailed **transaction reports** for your accounting and analytics.

---

## Endpoints

| Endpoint | Description |
|----------|-------------|
| [Data sources](/developers/rest-api/reference/data/data-sources/) | Manage connected data sources |
| [Customers](/developers/rest-api/reference/data/customers/) | Import and manage customer records |
| [Plans](/developers/rest-api/reference/data/plans/) | Import and manage subscription plans |
| [Plan groups](/developers/rest-api/reference/data/plan-groups/) | Organize plans into groups for reporting |
| [Invoices](/developers/rest-api/reference/data/invoices/) | Import and manage invoices |

---

## How it works

1. **Send data via API**
   Use the endpoints under `/data/customers`, `/data/plans`, and `/data/invoices` to push your external data into GrowPanel.

2. **Validation and deduplication**
   The API validates required fields, checks for duplicates, and performs bulk upserts when needed.

3. **Data processing**
   Once imported, the system automatically updates your **MRR and transaction reports**, calculating all relevant metrics and movements.

4. **Reporting**
   You can then query the **reports endpoints** to get full analytics for your account, including historical trends and customer insights.

---

## Example workflow

1. Export your data from your billing system.
2. Use the Import Data API to send customers, plans, and invoices to GrowPanel.
3. Wait for the system to process the data (usually a few seconds for bulk imports).
4. Query the **MRR reports** and **transactions reports** endpoints to view updated metrics.

---

By using the Import Data API, you ensure your reports are **always accurate and up to date**, regardless of your external billing platform.

---

## Invoices
<!-- url: https://growpanel.io/developers/rest-api/reference/data/invoices -->

The **Invoices API** lets you manage invoice data for your account. You can list invoices imported from your data sources, or perform bulk upserts (insert or update) of invoices.  
Invoices are typically tied to customers and plans, and can represent subscription charges, one-time payments, refunds, or cancellations.

---

## List invoices

Retrieve recent invoices stored in your connected data sources. You can optionally filter by data source or limit the number of returned invoices.

**Endpoint:** `GET /data/invoices`

**Query parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `source` | string | Required. The UUID of the [data source](../data-sources) the invoices belong to. |
| `limit` | integer | Optional. Limit the number of invoices returned. |

**Example request:**

```http
GET /data/invoices?source=2f7a9e3e-4f6d-4a3c-8b2a-0f1b4e7d8c9a&limit=5
Authorization: Bearer YOUR_API_KEY
````

### Example response

```json
{
  "result": {
    "count": 2,
    "list": [
      {
        "source_id": "2f7a9e3e-4f6d-4a3c-8b2a-0f1b4e7d8c9a",
        "customer_id": "cus_123",
        "id": "inv_001",
        "type": "subscription",
        "date": "2024-07-01T00:00:00Z",
        "amount_cents": 9900,
        "currency": "USD",
        "plan_id": "plan_123",
        "subscription_id": "sub_001",
        "start_date": "2024-07-01T00:00:00Z",
        "end_date": "2024-08-01T00:00:00Z",
        "quantity": 1,
        "discount": 0
      },
      {
        "source_id": "2f7a9e3e-4f6d-4a3c-8b2a-0f1b4e7d8c9a",
        "customer_id": "cus_456",
        "id": "inv_002",
        "type": "one-time",
        "date": "2024-07-02T00:00:00Z",
        "amount_cents": 15000,
        "currency": "USD",
        "start_date": "2024-07-02T00:00:00Z",
        "end_date": "2024-07-02T00:00:00Z"
      }
    ]
  }
}
```

---

## Create or bulk upsert invoices

Add new invoices or update existing ones in bulk.
Each invoice must include `id`, `customer_id`, `data_source`, `type`, `date`, `amount_cents`, `currency`, `start_date`, and `end_date`.

**Endpoint:** `POST /data/invoices`

**Request body (single invoice example):**

```json
{
  "id": "inv_001",
  "customer_id": "cus_123",
  "data_source": "stripe",
  "type": "subscription",
  "date": "2024-07-01T00:00:00Z",
  "amount_cents": 9900,
  "currency": "USD",
  "plan_id": "plan_123",
  "subscription_id": "sub_001",
  "start_date": "2024-07-01T00:00:00Z",
  "end_date": "2024-08-01T00:00:00Z",
  "quantity": 1,
  "discount": 0
}
```

**Request body (bulk example):**

```json
[
  {
    "id": "inv_001",
    "customer_id": "cus_123",
    "data_source": "stripe",
    "type": "subscription",
    "date": "2024-07-01T00:00:00Z",
    "amount_cents": 9900,
    "currency": "USD",
    "plan_id": "plan_123",
    "subscription_id": "sub_001",
    "start_date": "2024-07-01T00:00:00Z",
    "end_date": "2024-08-01T00:00:00Z"
  },
  {
    "id": "inv_002",
    "customer_id": "cus_456",
    "data_source": "stripe",
    "type": "one-time",
    "date": "2024-07-02T00:00:00Z",
    "amount_cents": 15000,
    "currency": "USD",
    "start_date": "2024-07-02T00:00:00Z",
    "end_date": "2024-07-02T00:00:00Z"
  }
]
```

### Example response

```json
{
  "result": [
    { "id": "inv_001", "import_status": "inserted" },
    { "id": "inv_002", "import_status": "inserted" }
  ]
}
```

### Validation errors

Validation errors are returned if required fields are missing, dates are invalid, or referenced customers or plans do not exist.

```json
{
  "result": [
    {
      "id": "inv_003",
      "import_status": "error",
      "import_error": "Missing invoice ID"
    },
    {
      "id": "inv_004",
      "import_status": "error",
      "import_error": "Plan ID plan_999 does not exist"
    }
  ]
}
```

### Notes

* `type` must be one of: `"subscription"`, `"one-time"`, `"refund"`, or `"cancellation"`.
* `amount_cents` must be a non-negative number.
* `currency` must be a 3-letter ISO currency code.
* `customer_id` must exist in your imported customers list.
* `plan_id` must exist in your imported plans list.
* When invoices are inserted or updated, related customers are automatically queued for metric recalculation. This process happens asynchronously after the API call returns.

---

### Example unchanged and updated responses

If you send an invoice identical to an existing one:

```json
{
  "result": [
    { "id": "inv_001", "import_status": "unchanged" }
  ]
}
```

If you update an existing invoice:

```json
{
  "result": [
    { "id": "inv_001", "import_status": "updated" }
  ]
}

---

## Plan groups
<!-- url: https://growpanel.io/developers/rest-api/reference/data/plan_groups -->

The **Plan Groups API** allows you to manage plan groups for your account. Each group can have a number of plans in them, organized in the way that makes most sense for your reporting. You can list, create, update, and delete plan groups, and control the plans inside them.

## List plan groups

Retrieve all plan groups for your account. You can optionally limit the number of returned plans.

**Endpoint:** `GET /data/plan-groups`

**Query parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `limit` | integer | Optional. Limit the number of plans returned. |

**Example request:**

```http
GET /data/plan-groups?limit=100
Authorization: Bearer YOUR_API_KEY
```

### Example response

```json
{
    "result": {
        "count": 5,
        "list": [
            {
                "id": "b8d2d779-fdc7-4df0-89ee-88b5397a4b28",
                "name": "Growth",
                "plans": [
                    {
                        "id": "price_1LvNamxxqqZbQ9jJmRjpZevo",
                        "name": "Growth Monthly (EUR)",
                        "billing_freq": "month",
                        "billing_freq_count": 1,
                        "product_name": "Growth",
                        "currency": "eur"
                    },
                    {
                        "id": "price_1LskeDssUqqZbQ9jJjGxZLKfu",
                        "name": "Growth Yearly (USD)",
                        "billing_freq": "year",
                        "billing_freq_count": 1,
                        "product_name": "Growth",
                        "currency": "usd"
                    }
                ]
            },
            {
                "id": "e12df8c4-78db-421d-919a-0f094905024d",
                "name": "Pro",
                "plans": [
                    {
                        "id": "price_1LvNcxxFUqqZbQ9jJZLJX83C4",
                        "name": "Pro Monthly (USD)",
                        "billing_freq": "month",
                        "billing_freq_count": 1,
                        "product_name": "Pro",
                        "currency": "usd"
                    },
                    ...
                ]
            }
        ]
    }
}
```

---

## Create plan groups

Add a new plan group including the relationship to the plans in the group. The plans are referred by their ID only, and must exist beforehand.

**Endpoint:** `POST /data/plan-groups`

**Request body:**

```json
{
    "name": "Growth",
    "plans": [
        {
            "id": "price_1LvNamxxqqZbQ9jJmRjpZevo"
        },
        {
            "id": "price_1LskeDssUqqZbQ9jJjGxZLKfu"
        }
    ]
}
```

**Example response:**

```json
{
    "success": true,
    "id": "b8d2d779-fdc7-4df0-89ee-88b5397a4b28"
}
```

---

## Update a plan group

Update an existing plan by its external ID. You can update the names and the list of plans.

**Endpoint:** `PUT /data/plan-groups/:id`

**Request body:**

```json
{
    "name": "Growth",
    "plans": [
        {
            "id": "price_1LvNamxxqqZbQ9jJmRjpZevo"
        }
    ]
}
```

**Example response:**

```json
{
  "success": true,
  "id": "b8d2d779-fdc7-4df0-89ee-88b5397a4b28"
}
```

---

## Delete a plan group

Delete a plan group by its external ID, including the group's relationship to its plans. The plans themselves are not deleted.

**Endpoint:** `DELETE /data/plan-groups/:id`

**Example response:**

```json
{
  "success": true,
  "id": "b8d2d779-fdc7-4df0-89ee-88b5397a4b28"
}
```

---

## Plans
<!-- url: https://growpanel.io/developers/rest-api/reference/data/plans -->

The **Plans API** allows you to manage subscription plans for your account. You can list, create, update, and delete plans, as well as perform bulk upserts. Plans include details such as billing frequency, product name, and currency.

## List plans

Retrieve all plans for your account. You can optionally filter by data source or limit the number of returned plans.

**Endpoint:** `GET /data/plans`

**Query parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `source` | string | Optional. Filter plans by data source. |
| `limit` | integer | Optional. Limit the number of plans returned. |

**Example request:**

```http
GET /data/plans?source=stripe&limit=5
Authorization: Bearer YOUR_API_KEY
````

### Example response

```json
{
  "result": {
    "count": 5,
    "list": [
      {
        "id": "plan_123",
        "name": "Pro Plan",
        "billing_freq": "month",
        "billing_freq_count": 1,
        "product_name": "Pro Subscription",
        "currency": "USD"
      }
    ]
  }
}
```

---

## Create or bulk upsert plans

Add a new plan or update existing ones in bulk. Each plan must include `id`, `name`, `billing_freq`, and `currency`.

**Endpoint:** `POST /data/plans`

**Request body (single plan example):**

```json
{
  "id": "plan_123",
  "name": "Pro Plan",
  "billing_freq": "month",
  "billing_freq_count": 1,
  "currency": "USD",
  "product_name": "Pro Subscription",
  "data_source": "stripe"
}
```

**Request body (bulk example):**

```json
[
  {
    "id": "plan_123",
    "name": "Pro Plan",
    "billing_freq": "month",
    "billing_freq_count": 1,
    "currency": "USD",
    "product_name": "Pro Subscription",
    "data_source": "stripe"
  },
  {
    "id": "plan_456",
    "name": "Basic Plan",
    "billing_freq": "month",
    "billing_freq_count": 1,
    "currency": "USD",
    "product_name": "Basic Subscription",
    "data_source": "stripe"
  }
]
```

**Example response:**

```json
{
  "result": [
    { "id": "plan_123", "import_status": "inserted" },
    { "id": "plan_456", "import_status": "inserted" }
  ]
}
```

**Validation errors** are returned if required fields are missing or invalid:

```json
{
  "result": [
    {
      "id": "plan_789",
      "import_status": "error",
      "import_error": "Missing required fields"
    }
  ]
}
```

---

## Update a plan

Update an existing plan by its external ID.

**Endpoint:** `PUT /data/plans/:id`

**Request body:**

```json
{
  "name": "Pro Plan Updated",
  "billing_freq": "month",
  "billing_freq_count": 1,
  "currency": "USD",
  "product_name": "Pro Subscription"
}
```

**Example response:**

```json
{
  "result": "ok",
  "updated": "plan_123"
}
```

**Error response if `id` is missing:**

```json
{
  "error": "Missing external_id"
}
```

---

## Delete a plan

Delete a plan by its external ID.

**Endpoint:** `DELETE /data/plans/:id`

**Example response:**

```json
{
  "result": "ok",
  "deleted": "plan_123"
}
```

**Error response if `id` is missing:**

```json
{
  "error": "Missing external_id"
}
```

---

## API Reference
<!-- url: https://growpanel.io/developers/rest-api/reference/ -->

Comprehensive reference for all GrowPanel API endpoints. All APIs are HTTP-based and return JSON responses.

**Base URL:** `https://api.growpanel.io`

---

## Endpoint categories

### [MRR reports](/developers/rest-api/reference/reports/)
MRR, churn, cohort, and segmentation reports.

### [Leads & trials](/developers/rest-api/reference/leads-trials/)
Lead, trial, and conversion funnel reports.

### [Cashflow reports](/developers/rest-api/reference/cashflow/)
Transaction, failed payment, refund, and outstanding invoice reports.

### [Data](/developers/rest-api/reference/data/)
Push and retrieve customers, plans, invoices, and data sources.

### [Customers](/developers/rest-api/reference/customers/)
Retrieve customer information and subscription history.

### [Account](/developers/rest-api/reference/account/)
Manage account settings, team members, and API keys.

### [Settings](/developers/rest-api/reference/settings/)
Configure integrations and notification preferences.

---

## Authentication

All requests require an API key in the Authorization header:

```bash
curl https://api.growpanel.io/v1/reports/mrr \
  -H "Authorization: Bearer YOUR_API_KEY"
```

See [Authentication](/developers/rest-api/authentication/) for details on obtaining API keys.

---

## Response format

Successful requests return JSON with HTTP 2xx status codes:

```json
{
  "data": { ... },
  "meta": { ... }
}
```

Failed requests return error details. See [Error codes](/developers/rest-api/error-codes/) for the full list.

---

## Leads & trials
<!-- url: https://growpanel.io/developers/rest-api/reference/leads-trials/ -->

Endpoints for **lead**, **trial**, and **conversion funnel** reports.

---

| Endpoint | Description |
|----------|-------------|
| [GET /reports/leads](/developers/rest-api/reference/leads-trials/leads/) | Lead and trial timeline |
| [GET /reports/leads-days](/developers/rest-api/reference/leads-trials/leads-days/) | Lead conversion day distribution |
| [GET /reports/leads-summary](/developers/rest-api/reference/leads-trials/leads-summary/) | Lead summary metrics |

---

## Lead conversion days
<!-- url: https://growpanel.io/developers/rest-api/reference/leads-trials/leads-days -->

The `/reports/leads-days` endpoint returns a distribution of how many days it takes for leads to convert to paid customers. This is useful for understanding your sales cycle length and optimizing your conversion funnel.

> 💡 **Use case**: Analyze sales cycle duration, identify optimal follow-up timing, benchmark conversion speeds across segments.

## GET /reports/leads-days

Returns a distribution of lead-to-paid conversion times.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/leads-days \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Date range. Format: <code>YYYYMMDD-YYYYMMDD</code> or shortcuts like <code>last-12-months</code>.</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns an array of conversion time buckets with percentages.

```json
{
  "result": [
    { "days": 0, "percent": 15.2 },
    { "days": 1, "percent": 8.5 },
    { "days": 7, "percent": 12.3 },
    { "days": 14, "percent": 18.7 },
    { "days": 30, "percent": 25.1 },
    { "days": 60, "percent": 12.8 },
    { "days": 90, "percent": 7.4 }
  ]
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>days</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Number of days from lead creation to paid subscription start</td>
    </tr>
    <tr>
      <td><code>percent</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage of conversions at this day count (0-100)</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get overall conversion distribution**
```bash
curl https://api.growpanel.io/reports/leads-days \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by channel**
```bash
curl "https://api.growpanel.io/reports/leads-days?channel=organic" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Compare by region**
```bash
curl "https://api.growpanel.io/reports/leads-days?region=us" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Analyze last 6 months**
```bash
curl "https://api.growpanel.io/reports/leads-days?date=last-6-months" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

- **Day buckets**: Results are grouped into common time buckets (0, 1, 7, 14, 30, 60, 90 days)
- **Same-day conversion**: `days: 0` represents leads that converted on the same day they were created
- **Percentages**: All percentages sum to 100% across all buckets
- **Sales cycle insight**: Most SaaS products see peaks at 0, 7, 14, and 30 days
- **Segmentation**: Use filters to compare conversion speeds across different segments

### Related endpoints

- [Leads Summary](/developers/rest-api/reference/leads-trials/leads-summary/) - Lead snapshot metrics
- [Leads](/developers/rest-api/reference/leads-trials/leads/) - Detailed lead funnel analysis

---

## Leads summary
<!-- url: https://growpanel.io/developers/rest-api/reference/leads-trials/leads-summary -->

The `/reports/leads-summary` endpoint returns lead and trial counts at different historical points (30, 60, 180, 365 days) with percentage changes, similar to the [summary metrics](/developers/rest-api/reference/reports/summary/) endpoint but focused on leads and trials.

> 💡 **Use case**: Track lead generation growth over time. Monitor trial conversion trends. Build executive dashboards showing funnel performance.

## GET /reports/leads-summary

Returns lead and trial snapshots at historical points with growth percentages.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/leads-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated). Example: <code>us ca</code></td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a `summary` object with lead and trial metrics over time.

```json
{
  "summary": {
    "leads_30": 150,
    "leads_60": 140,
    "leads_180": 120,
    "leads_365": 90,
    "trials_30": 80,
    "trials_60": 75,
    "trials_180": 60,
    "trials_365": 45,
    "leads_percentage_change_30": 7.1,
    "leads_percentage_change_60": 14.3,
    "leads_percentage_change_180": 25.0,
    "leads_percentage_change_365": 66.7,
    "trials_percentage_change_30": 6.7,
    "trials_percentage_change_60": 13.3,
    "trials_percentage_change_180": 33.3,
    "trials_percentage_change_365": 77.8
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Lead Counts</td>
    </tr>
    <tr>
      <td><code>leads_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New leads in the last 30 days</td>
    </tr>
    <tr>
      <td><code>leads_60</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New leads in the last 60 days</td>
    </tr>
    <tr>
      <td><code>leads_180</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New leads in the last 180 days</td>
    </tr>
    <tr>
      <td><code>leads_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New leads in the last 365 days</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Trial Counts</td>
    </tr>
    <tr>
      <td><code>trials_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New trials in the last 30 days</td>
    </tr>
    <tr>
      <td><code>trials_60</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New trials in the last 60 days</td>
    </tr>
    <tr>
      <td><code>trials_180</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New trials in the last 180 days</td>
    </tr>
    <tr>
      <td><code>trials_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>New trials in the last 365 days</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Percentage Changes</td>
    </tr>
    <tr>
      <td><code>leads_percentage_change_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage change in leads vs prior 30-day period</td>
    </tr>
    <tr>
      <td><code>leads_percentage_change_60/180/365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage changes over 60, 180, and 365 day periods</td>
    </tr>
    <tr>
      <td><code>trials_percentage_change_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage change in trials vs prior 30-day period</td>
    </tr>
    <tr>
      <td><code>trials_percentage_change_60/180/365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage changes over 60, 180, and 365 day periods</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get overall leads summary**
```bash
curl https://api.growpanel.io/reports/leads-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by channel**
```bash
curl "https://api.growpanel.io/reports/leads-summary?channel=organic" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Compare regions**
```bash
curl "https://api.growpanel.io/reports/leads-summary?region=us" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by industry**
```bash
curl "https://api.growpanel.io/reports/leads-summary?industry=saas" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

- **Rolling periods**: Each period represents a rolling window (e.g., leads_30 = leads from last 30 days)
- **Growth calculation**: Percentage change compares current period to the equivalent prior period
- **Positive vs negative**: Positive percentages indicate growth, negative indicate decline
- **Lead vs Trial**: Leads are prospects, trials are active trial users
- **Filtering**: All filter parameters work together (AND logic) to narrow down results

### Related endpoints

- [Lead Conversion Days](/developers/rest-api/reference/leads-trials/leads-days/) - Conversion time distribution
- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - MRR and customer snapshots

---

## Leads and trials
<!-- url: https://growpanel.io/developers/rest-api/reference/leads-trials/leads -->

The **Leads API** provides a **timeline of leads, trials, and conversions** for your account. It aggregates customers by period, calculates conversion rates, lead-to-paid durations, and forecasts for unfinished periods. This is useful to monitor the efficiency of your acquisition and trial-to-paid conversion processes.

---

## List leads

**Endpoint:** `GET /reports/leads`

Retrieve leads and trial statistics aggregated by time interval.

### Query parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `interval` | string | Period for aggregation: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `date` | string | Anchor date for the range. Format: `YYYYMMDD-YYYYMMDD`. Defaults to last 365 days |
| `region` | string | Space-separated region names or country codes. |
| `currency` | string | Space-separated currency codes to filter customers. |
| `industry` | string | Space-separated industries. |
| `channel` | string | Space-separated channels. |
| `size` | string | Space-separated customer sizes. |

---

## Response structure

The API returns an array of periods with metrics:

| Field | Type | Description |
|-------|------|-------------|
| `date` | string | Start date of the period (ISO format). |
| `leads` | integer | Number of new leads in the period. |
| `leads_percent_change` | float | % change compared to previous period. |
| `trials` | integer | Number of trials started in the period. |
| `trials_percent_change` | float | % change compared to previous period. |
| `leads_converted` | integer | Number of leads converted to paying customers. |
| `trials_converted` | integer | Number of trials converted to paying customers. |
| `lead_to_trial_rate` | float | % of leads that started trials. |
| `lead_to_trial_rate_percent_change` | float | % change compared to previous period. |
| `trial_to_paid_rate` | float | % of trials that converted to paying customers. |
| `trial_to_paid_rate_percent_change` | float | % change compared to previous period. |
| `lead_to_paid_rate` | float | % of leads that converted to paying customers. |
| `lead_to_paid_rate_percent_change` | float | % change compared to previous period. |
| `lead_to_paid_days` | integer | Average days from lead creation to paid start. |
| `trial_to_paid_days` | integer | Average days from trial start to paid start. |
| `leads_forecast` | integer | Forecasted leads for unfinished periods. |
| `trials_forecast` | integer | Forecasted trials for unfinished periods. |
| `conversions_forecast` | integer | Forecasted conversions for unfinished periods. |
| `trial_to_paid_rate_forecast` | float | Forecasted trial-to-paid conversion rate for unfinished periods. |

---

## Example request

```http
GET /reports/leads?interval=month&region=us+europe&currency=usd+eur&date=20250101-20250701
````

---

## Example response

```json
{
  "result": [
    {
      "date": "2024-01-01",
      "leads": 150,
      "leads_percent_change": 10,
      "trials": 80,
      "trials_converted": 50,
      "leads_converted": 45,
      "trials_percent_change": 5,
      "lead_to_trial_rate": 53.33,
      "lead_to_trial_rate_percent_change": 2.5,
      "trial_to_paid_rate": 62,
      "trial_to_paid_rate_percent_change": 1.2,
      "lead_to_paid_rate": 30,
      "lead_to_paid_rate_percent_change": 1.1,
      "lead_to_paid_days": 12,
      "trial_to_paid_days": 8,
      "leads_forecast": 160,
      "trials_forecast": 85,
      "conversions_forecast": 52,
      "trial_to_paid_rate_forecast": 61
    }
  ]
}
```

---

## Notes

* Metrics are **aggregated per period** based on customer creation and trial dates.
* Forecasted values are only returned for **unfinished periods**.
* Filters allow granular segmentation by region, currency, industry, channel, and size.
* `lead_to_trial_rate`, `trial_to_paid_rate`, and `lead_to_paid_rate` provide insight into your funnel efficiency.

---

## Scheduled churn movements
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/churn-scheduled-movements -->

The `/reports/churn-scheduled-movements` endpoint returns individual customer-level detail for scheduled churn in a given period. This complements the [scheduled churn](/developers/rest-api/reference/reports/churn-scheduled/) summary by showing which specific customers are scheduled to churn and by how much.

> 💡 **Use case**: Identify at-risk customers, reach out to prevent churn, export scheduled cancellations for retention campaigns.

## GET /reports/churn-scheduled-movements

Returns a list of scheduled churn movements with customer details.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/churn-scheduled-movements \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>selected-date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Period start date to show movements for (format: <code>YYYY-MM-DD</code>).</td>
    </tr>
    <tr>
      <td><code>selected-type</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Churn type: <code>month_churn</code>, <code>year_churn</code>, <code>quarter_churn</code>, <code>week_churn</code>, <code>day_churn</code></td>
    </tr>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency.</td>
    </tr>
    <tr>
      <td><code>interval</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Aggregation interval. Defaults to <code>month</code>.</td>
    </tr>
    <tr>
      <td><code>breakdown</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Group by dimension (e.g., <code>plan</code>, <code>country</code>).</td>
    </tr>
    <tr>
      <td><code>breakdown-value</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter to a specific breakdown value.</td>
    </tr>
    <tr>
      <td><code>fix_fx</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">boolean</span></td>
      <td>Use fixed exchange rates.</td>
    </tr>
    <tr>
      <td><code>customer</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer ID.</td>
    </tr>
    <tr>
      <td><code>sort</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort field (e.g., <code>mrr_change</code>, <code>date</code>).</td>
    </tr>
    <tr>
      <td><code>order</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort direction: <code>asc</code> or <code>desc</code>.</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a list of scheduled churn movements.

```json
{
  "result": {
    "list": [
      {
        "date": "2025-03-01",
        "currency": "usd",
        "customer_id": "cus_456",
        "customer_name": "Beta LLC",
        "customer_email": "admin@beta.com",
        "type": "churn",
        "mrr_change": -4900,
        "mrr_change_base_currency": -4900,
        "description": "Pro Plan cancellation"
      },
      {
        "date": "2025-03-15",
        "currency": "eur",
        "customer_id": "cus_789",
        "customer_name": "Gamma GmbH",
        "customer_email": "billing@gamma.de",
        "type": "churn",
        "mrr_change": -9900,
        "mrr_change_base_currency": -10692,
        "description": "Enterprise Plan cancellation"
      }
    ]
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Scheduled churn date (ISO format: YYYY-MM-DD)</td>
    </tr>
    <tr>
      <td><code>currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Original currency of the subscription</td>
    </tr>
    <tr>
      <td><code>customer_id</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer external ID from billing system</td>
    </tr>
    <tr>
      <td><code>customer_name</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer name</td>
    </tr>
    <tr>
      <td><code>customer_email</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer email address</td>
    </tr>
    <tr>
      <td><code>type</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Movement type (always <code>churn</code>)</td>
    </tr>
    <tr>
      <td><code>mrr_change</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR change in original currency (cents, negative)</td>
    </tr>
    <tr>
      <td><code>mrr_change_base_currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR change in base currency (cents, negative)</td>
    </tr>
    <tr>
      <td><code>description</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Description of the scheduled change</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get all scheduled churn**
```bash
curl https://api.growpanel.io/reports/churn-scheduled-movements \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get churn scheduled for March 2025**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-movements?selected-date=2025-03-01" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get monthly churn only**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-movements?selected-type=month_churn" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Sort by largest churn amounts**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-movements?sort=mrr_change&order=asc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Churn amounts are negative. Divide by 100 for display.</p>
</div>

- **Scheduled churn**: Based on subscription end dates and cancellation schedules from your billing system
- **Proactive retention**: Use this data to identify and reach out to at-risk customers before they churn
- **Accuracy**: Depends on accurate subscription schedule data synced from Stripe, Chargebee, or Recurly
- **Churn types**: Filter by billing frequency to focus on monthly vs annual churn
- **Customer detail**: Includes contact information for retention outreach

### Related endpoints

- [Churn Scheduled](/developers/rest-api/reference/reports/churn-scheduled/) - Aggregated scheduled churn timeline
- [Scheduled Churn Summary](/developers/rest-api/reference/reports/churn-scheduled-summary/) - Historical churn snapshots
- [Movement Table](/developers/rest-api/reference/reports/movement-table/) - Actual (past) churn movements

---

## Scheduled churn summary
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/churn-scheduled-summary -->

The `/reports/churn-scheduled-summary` endpoint returns scheduled churn values at different historical points (current, 30, 60, 180, 365 days ago), similar to the [summary metrics](/developers/rest-api/reference/reports/summary/) endpoint but focused on scheduled churn.

> 💡 **Use case**: Track how scheduled churn has evolved over time. Monitor trends in cancellation patterns and retention effectiveness.

## GET /reports/churn-scheduled-summary

Returns scheduled churn snapshots at current and historical points.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/churn-scheduled-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency (e.g., <code>usd</code>).</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated). Example: <code>us ca</code> or <code>eu</code></td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated). Example: <code>usd eur gbp</code></td>
    </tr>
    <tr>
      <td><code>plan</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by plan group IDs (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a `summary` object with scheduled churn values at different time points.

```json
{
  "currency": "usd",
  "summary": {
    "churn_current": -4200,
    "churn_30": -3800,
    "churn_60": -5100,
    "churn_180": -2900,
    "churn_365": -6500
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Reporting currency (ISO 4217 code)</td>
    </tr>
    <tr>
      <td><code>churn_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Current scheduled churn MRR (cents, negative)</td>
    </tr>
    <tr>
      <td><code>churn_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Scheduled churn from 30 days ago (cents, negative)</td>
    </tr>
    <tr>
      <td><code>churn_60</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Scheduled churn from 60 days ago (cents, negative)</td>
    </tr>
    <tr>
      <td><code>churn_180</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Scheduled churn from 180 days ago (cents, negative)</td>
    </tr>
    <tr>
      <td><code>churn_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Scheduled churn from 365 days ago (cents, negative)</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get overall scheduled churn summary**
```bash
curl https://api.growpanel.io/reports/churn-scheduled-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by region**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-summary?region=eu" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by plan**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-summary?plan=plan_123" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Convert to EUR**
```bash
curl "https://api.growpanel.io/reports/churn-scheduled-summary?baseCurrency=eur" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Churn amounts are negative. Divide by 100 for display.</p>
</div>

- **Historical comparison**: Track how your scheduled churn has changed over time
- **Trend analysis**: Increasing scheduled churn may indicate retention issues
- **Negative values**: All churn amounts are negative to represent revenue loss
- **Snapshot data**: Each value represents what scheduled churn was at that specific point in time
- **Retention effectiveness**: Compare trends to measure retention campaign impact

### Related endpoints

- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - MRR and ARR snapshots
- [Churn Scheduled](/developers/rest-api/reference/reports/churn-scheduled/) - Detailed scheduled churn timeline
- [Scheduled Churn Movements](/developers/rest-api/reference/reports/churn-scheduled-movements/) - Individual customer detail

---

## Scheduled churn
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/churn-scheduled -->

The `/reports/churn-scheduled` endpoint provides a forward-looking view of scheduled churn, showing expected MRR and customer losses over the next 12 months. This report helps forecast revenue impact from upcoming subscription cancellations and plan retention efforts.

---

## HTTP request

```
GET /reports/churn-scheduled
````

## Query parameters

| Parameter        | Type     | Required | Description |
|------------------|---------|----------|-------------|
| `interval`       | string  | No       | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency`   | string  | No       | Target currency for MRR conversion. Defaults to the user's base currency. |
| `region`         | string  | No       | Filter by region name(s) or country code(s). Multiple values separated by spaces. |
| `currency`       | string  | No       | Filter by customer currency. Multiple values separated by spaces. |
| `industry`       | string  | No       | Filter by industry. Multiple values separated by spaces. |
| `channel`        | string  | No       | Filter by sales or marketing channel. Multiple values separated by spaces. |
| `size`           | string  | No       | Filter by company size. Multiple values separated by spaces. |

---

## Response

### Success 

**Status:** 200 OK  

**Body example:**

```json
[
  {
    "date": "2025-10-01",
    "mrr_diff": -1200,
    "customers_diff": -3,
    "churn": -1200,
    "churn_customers": 3,
    "month_churn": -1200,
    "month_churn_customers": 3,
    "year_churn": -1200,
    "year_churn_customers": 3,
    "total_mrr": 48000,
    "total_arr": 576000,
    "total_customers": 150
  },
  {
    "date": "2025-11-01",
    "mrr_diff": -800,
    "customers_diff": -2,
    "churn": -800,
    "churn_customers": 2,
    "month_churn": -800,
    "month_churn_customers": 2,
    "year_churn": -800,
    "year_churn_customers": 2,
    "total_mrr": 47200,
    "total_arr": 566400,
    "total_customers": 148
  }
]
```

## Response fields

| Field                     | Type   | Description                                                              |
| ------------------------- | ------ | ------------------------------------------------------------------------ |
| `date`                    | string | The start of the period.                                                 |
| `mrr_diff`                | number | MRR scheduled to churn in this period (converted to base currency).      |
| `customers_diff`          | number | Number of customers scheduled to churn.                                  |
| `churn`                   | number | Same as `mrr_diff`, for clarity.                                         |
| `churn_customers`         | number | Same as `customers_diff`, for clarity.                                   |
| `month_churn`             | number | MRR scheduled to churn with monthly billing frequency.                   |
| `month_churn_customers`   | number | Number of customers scheduled to churn with monthly billing frequency.   |
| `year_churn`              | number | MRR scheduled to churn with yearly billing frequency.                    |
| `year_churn_customers`    | number | Number of customers scheduled to churn with yearly billing frequency.    |
| `week_churn`              | number | MRR scheduled to churn with weekly billing frequency.                    |
| `week_churn_customers`    | number | Number of customers scheduled to churn with weekly billing frequency.    |
| `day_churn`               | number | MRR scheduled to churn with daily billing frequency.                     |
| `day_churn_customers`     | number | Number of customers scheduled to churn with daily billing frequency.     |
| `quarter_churn`           | number | MRR scheduled to churn with quarterly billing frequency.                 |
| `quarter_churn_customers` | number | Number of customers scheduled to churn with quarterly billing frequency. |
| `total_mrr`               | number | Total projected MRR at the end of the period (base currency).            |
| `total_arr`               | number | Total projected ARR (MRR × 12).                                          |
| `total_customers`         | number | Total number of customers at the end of the period.                      |

---

This endpoint is ideal for **forecasting revenue impact** from upcoming subscription churn, helping teams prioritize retention actions and understand expected MRR loss over different billing frequencies.

---

## CMRR summary
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/cmrr-summary -->

The `/reports/cmrr-summary` endpoint returns Committed Monthly Recurring Revenue (CMRR) values at different historical points. CMRR includes scheduled future subscription changes, giving a forward-looking view of expected recurring revenue.

> 💡 **Use case**: Forecast revenue with scheduled changes. Track CMRR trends over time to understand future revenue commitments and compare to actual MRR.

## GET /reports/cmrr-summary

Returns CMRR snapshots at current and historical points (30, 60, 180, 365 days ago).

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/cmrr-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency (e.g., <code>usd</code>).</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated). Example: <code>us ca</code> or <code>eu</code></td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated). Example: <code>usd eur gbp</code></td>
    </tr>
    <tr>
      <td><code>plan</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by plan group IDs (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a `summary` object with CMRR values at different time points.

```json
{
  "currency": "usd",
  "summary": {
    "cmrr_current": 135000,
    "cmrr_30": 130000,
    "cmrr_60": 125000,
    "cmrr_180": 110000,
    "cmrr_365": 90000
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Reporting currency (ISO 4217 code)</td>
    </tr>
    <tr>
      <td><code>cmrr_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Current committed MRR including scheduled changes (cents)</td>
    </tr>
    <tr>
      <td><code>cmrr_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>CMRR from 30 days ago (cents)</td>
    </tr>
    <tr>
      <td><code>cmrr_60</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>CMRR from 60 days ago (cents)</td>
    </tr>
    <tr>
      <td><code>cmrr_180</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>CMRR from 180 days ago (cents)</td>
    </tr>
    <tr>
      <td><code>cmrr_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>CMRR from 365 days ago (cents)</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get overall CMRR summary**
```bash
curl https://api.growpanel.io/reports/cmrr-summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by region**
```bash
curl "https://api.growpanel.io/reports/cmrr-summary?region=eu" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by plan**
```bash
curl "https://api.growpanel.io/reports/cmrr-summary?plan=plan_123" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Convert to EUR**
```bash
curl "https://api.growpanel.io/reports/cmrr-summary?baseCurrency=eur" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Divide by 100 for display in most currencies.</p>
</div>

- **CMRR calculation**: Includes current MRR plus scheduled subscription changes (upgrades, downgrades, cancellations)
- **Historical snapshots**: Each value represents what CMRR was at that point in time
- **Trend analysis**: Compare CMRR over time to understand how future revenue expectations evolved
- **Accuracy**: CMRR accuracy depends on subscription schedule data from your billing system

### Related endpoints

- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - MRR and ARR snapshots
- [Churn Scheduled](/developers/rest-api/reference/reports/churn-scheduled/) - Detailed scheduled churn breakdown
- [MRR Table](/developers/rest-api/reference/reports/mrr-table/) - Time-series MRR data

---

## Cohorts
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/cohort -->

The `/reports/cohort` endpoint provides cohort-based analytics for your customers, including retention, churn, and MRR movements over time. This endpoint allows you to analyze customer behavior by time-based cohorts (e.g., by paid start date) or categorical cohorts (e.g., country or currency). It supports flexible filtering, currency conversion, and interval-based aggregation.

---

## HTTP request

```
GET /reports/cohort
````

---

## Query parameters

| Parameter        | Type     | Required | Description |
|------------------|---------|----------|-------------|
| `date`           | string  | No       | End date of the cohort period (YYYY-MM-DD). Defaults to current date. |
| `interval`       | string  | No       | Aggregation interval: `day`, `week`, `month`, `quarter`, `year`. Defaults to `month`. |
| `baseCurrency`   | string  | No       | Target currency for MRR conversion. Defaults to the user's base currency. |
| `breakdown`      | string  | No       | Optional breakdown of cohorts: `country`, `currency`. Defaults to time-based cohort by `paid_started`. |
| `fix_fx`         | boolean | No       | If `true`, uses exchange rates fixed to cohort start date instead of period-specific rates. Defaults to `false`. |
| `region`         | string  | No       | Filter by region name(s) or country code(s). Multiple values separated by spaces. |
| `currency`       | string  | No       | Filter by customer currency. Multiple values separated by spaces. |
| `industry`       | string  | No       | Filter by industry. Multiple values separated by spaces. |
| `channel`        | string  | No       | Filter by sales or marketing channel. Multiple values separated by spaces. |
| `size`           | string  | No       | Filter by company size. Multiple values separated by spaces. |

---

## Response

### Success (time-based cohort)

**Status:** 200 OK  

**Body example:**

```json
{
  "result": {
    "list": [
      {
        "cohort_group": "2024-01-31",
        "initial_mrr": 12000,
        "initial_customers": 15,
        "periods": [
          {
            "mrr_retained": 12000,
            "customers_retained": 15,
            "mrr_retention": 100,
            "customer_retention": 100,
            "mrr_retention_relative": 100,
            "customer_retention_relative": 100,
            "mrr_churn": 0,
            "customer_churn": 0,
            "mrr_churn_relative": 0,
            "customer_churn_relative": 0
          },
          {
            "mrr_retained": 11000,
            "customers_retained": 14,
            "mrr_retention": 91.67,
            "customer_retention": 93.33,
            "mrr_retention_relative": 91.67,
            "customer_retention_relative": 93.33,
            "mrr_churn": 8.33,
            "customer_churn": 6.67,
            "mrr_churn_relative": 8.33,
            "customer_churn_relative": 6.67
          }
        ]
      },
      {
        "cohort_group": "average",
        "periods": [
          {
            "mrr_retained": 23000,
            "customers_retained": 29,
            "mrr_retention": 96.67,
            "customer_retention": 96.67,
            "mrr_retention_relative": 100,
            "customer_retention_relative": 100,
            "mrr_churn": 3.33,
            "customer_churn": 3.33,
            "mrr_churn_relative": 0,
            "customer_churn_relative": 0
          }
        ]
      }
    ]
  }
}
````

### Success (country breakdown)

**Query:** `?format=chart&breakdown=country`

**Body example:**

```json
{
  "breakdown": "country",
  "result": [
    {
      "period": 0,
      "breakdown": {
        "US": {
          "label": "US",
          "mrr_retained": 5000,
          "customers_retained": 8,
          "mrr_retention": 100,
          "customer_retention": 100
        },
        "DE": {
          "label": "DE",
          "mrr_retained": 3000,
          "customers_retained": 5,
          "mrr_retention": 100,
          "customer_retention": 100
        }
      }
    }
  ]
}
```

---

## Response fields

| Field                         | Type   | Description                                                                                                    |
| ----------------------------- | ------ | -------------------------------------------------------------------------------------------------------------- |
| `cohort_group`                | string | The cohort identifier. Date for time-based cohorts or category value for breakdowns (e.g., country, currency). |
| `initial_mrr`                 | number | MRR at the start of the cohort (in base currency).                                                             |
| `initial_customers`           | number | Number of customers at the start of the cohort.                                                                |
| `periods`                     | array  | Array of periods relative to cohort start, containing retention metrics and MRR/customer changes.              |
| `mrr_retained`                | number | Total MRR retained for this period (base currency).                                                            |
| `customers_retained`          | number | Total customers retained for this period.                                                                      |
| `mrr_retention`               | number | Percentage of MRR retained relative to the cohort's initial MRR.                                               |
| `customer_retention`          | number | Percentage of customers retained relative to initial cohort size.                                              |
| `mrr_retention_relative`      | number | MRR retention relative to the previous period.                                                                 |
| `customer_retention_relative` | number | Customer retention relative to the previous period.                                                            |
| `mrr_churn`                   | number | Churned MRR percentage (100 - `mrr_retention`).                                                                |
| `customer_churn`              | number | Churned customer percentage (100 - `customer_retention`).                                                      |
| `mrr_churn_relative`          | number | Churned MRR percentage relative to previous period.                                                            |
| `customer_churn_relative`     | number | Churned customer percentage relative to previous period.                                                       |

---

## Usage notes

1. **Currency conversion:**
   The `baseCurrency` parameter converts all MRR amounts to a single currency. Exchange rates are either period-specific or fixed to cohort start (`fix_fx=true`).

2. **Interval handling:**

   * Day, week, month, quarter, year.
   * Daily cohorts are automatically aggregated weekly to avoid excessive granularity.

3. **Breakdowns:**

   * By default, cohorts are time-based (by `paid_started`).
   * Optional categorical breakdowns: `country` or `currency`.

4. **Empty cohorts:**
   Cohorts with no data return `0` values and are included to maintain continuity in the timeline.

5. **Chart-ready format:**
   When `format=chart` is used, the response is structured with `period` indexes and `breakdown` objects for easier visualization in dashboards.

---

This endpoint is ideal for tracking **cohort retention trends**, **MRR growth**, and **customer churn** over time, helping teams understand product adoption and revenue retention at a granular level.

---

## Custom variables
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/custom-variables -->

The `/reports/custom-variables` endpoint returns distinct values for a given custom variable key, useful for populating filter dropdowns and exploring available segmentation options.

> 💡 **Use case**: Build dynamic filter UIs, discover available custom variable values, implement autocomplete for custom dimensions.

## GET /reports/custom-variables

Returns a list of distinct values for a custom variable with usage counts.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/custom-variables \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>key</code><span class="text-red-400 text-xs ml-1">required</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>The custom variable key to retrieve values for (e.g., <code>industry</code>, <code>channel</code>, <code>segment</code>).</td>
    </tr>
    <tr>
      <td><code>search</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Search term to filter values (autocomplete). Case-insensitive partial match.</td>
    </tr>
    <tr>
      <td><code>limit</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Maximum number of values to return. Defaults to 20. Maximum: 100.</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a list of values with customer counts.

```json
{
  "values": [
    { "value": "enterprise", "count": 45 },
    { "value": "startup", "count": 120 },
    { "value": "agency", "count": 30 }
  ]
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>value</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>The custom variable value</td>
    </tr>
    <tr>
      <td><code>count</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Number of customers with this value</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get all industry values**
```bash
curl "https://api.growpanel.io/reports/custom-variables?key=industry" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Search for industries containing "tech"**
```bash
curl "https://api.growpanel.io/reports/custom-variables?key=industry&search=tech" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get top 50 channels**
```bash
curl "https://api.growpanel.io/reports/custom-variables?key=channel&limit=50" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Autocomplete for size segments**
```bash
curl "https://api.growpanel.io/reports/custom-variables?key=size&search=small" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Errors

<div class="space-y-3 mt-6">

<span class="inline-block bg-red-100 text-red-800 text-xs font-semibold px-2 py-1 rounded">400 Bad Request</span>

Missing or invalid `key` parameter.

```json
{
  "error": "Missing required parameter: key"
}
```

<span class="inline-block bg-red-100 text-red-800 text-xs font-semibold px-2 py-1 rounded">401 Unauthorized</span>

Invalid or missing API key.

```json
{
  "error": "Unauthorized"
}
```

</div>

### Notes

- **Custom variables**: Must be configured in your GrowPanel account and synced from your billing system
- **Sorting**: Results are sorted by count (descending) to show most common values first
- **Search**: The `search` parameter performs case-insensitive substring matching
- **Performance**: Responses are cached for 5 minutes to improve performance
- **Common keys**: Standard custom variable keys include `industry`, `channel`, `size`, `segment`, `market`

### Related endpoints

- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - Filter by custom variables
- [MRR Table](/developers/rest-api/reference/reports/mrr-table/) - Breakdown by custom variables
- [Map](/developers/rest-api/reference/reports/map/) - Geographic breakdown with custom filters

---

## Customer concentration
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/customer-concentration -->

The `/reports/customer-concentration` endpoint analyzes revenue concentration across your customer base. It shows how MRR is distributed among your top customers (Pareto analysis), helping identify revenue concentration risk.

> 💡 **Use case**: Assess revenue concentration risk, identify your most valuable customers, understand if you're over-dependent on a few large accounts.

## GET /reports/customer-concentration

Returns Pareto analysis of revenue distribution and concentration metrics.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/customer-concentration \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency.</td>
    </tr>
    <tr>
      <td><code>q</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Search by customer name, email, or ID.</td>
    </tr>
    <tr>
      <td><code>chart</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Set to <code>pareto</code> to return only pareto data for charting (omits detailed customer info).</td>
    </tr>
    <tr>
      <td><code>table</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Set to <code>1</code> to return data in table format with individual customer details.</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>age</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer age in months (e.g., <code>0-6</code>, <code>12-</code>).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns Pareto analysis with concentration metrics.

```json
{
  "result": {
    "pareto": [
      {
        "rank": 1,
        "name": "Acme Corp",
        "id": "cus_123",
        "mrr": 25000,
        "cumulative_mrr": 25000,
        "cumulative_pct": 20.0
      },
      {
        "rank": 2,
        "name": "Beta LLC",
        "id": "cus_456",
        "mrr": 15000,
        "cumulative_mrr": 40000,
        "cumulative_pct": 32.0
      },
      {
        "rank": "11-20",
        "mrr": 18000,
        "cumulative_mrr": 95000,
        "cumulative_pct": 76.0,
        "count": 10
      }
    ],
    "concentration": {
      "top_1": { "mrr": 25000, "pct": 20.0, "count": 1 },
      "top_5": { "mrr": 60000, "pct": 48.0, "count": 5 },
      "top_10": { "mrr": 77000, "pct": 61.6, "count": 10 },
      "top_100": { "mrr": 120000, "pct": 96.0, "count": 100 },
      "rest": { "mrr": 5000, "pct": 4.0, "count": 50 }
    },
    "count": 50,
    "summary": {
      "total_mrr": 125000,
      "total_customers": 150,
      "avg_mrr": 833,
      "median_mrr": 500
    }
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Pareto Array</td>
    </tr>
    <tr>
      <td><code>rank</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number or string</span></td>
      <td>Customer rank (1-10) or group label (e.g., "11-20")</td>
    </tr>
    <tr>
      <td><code>name</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer name (individual customers only)</td>
    </tr>
    <tr>
      <td><code>id</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer ID (individual customers only)</td>
    </tr>
    <tr>
      <td><code>mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR in base currency (cents)</td>
    </tr>
    <tr>
      <td><code>cumulative_mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Cumulative MRR up to this rank (cents)</td>
    </tr>
    <tr>
      <td><code>cumulative_pct</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Cumulative percentage of total MRR</td>
    </tr>
    <tr>
      <td><code>count</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Number of customers in group (grouped entries only)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Concentration Object</td>
    </tr>
    <tr>
      <td><code>top_1</code></td>
      <td><span class="text-purple-600 font-mono text-sm">object</span></td>
      <td>MRR, percentage, and count for top 1 customer</td>
    </tr>
    <tr>
      <td><code>top_5</code></td>
      <td><span class="text-purple-600 font-mono text-sm">object</span></td>
      <td>MRR, percentage, and count for top 5 customers</td>
    </tr>
    <tr>
      <td><code>top_10</code></td>
      <td><span class="text-purple-600 font-mono text-sm">object</span></td>
      <td>MRR, percentage, and count for top 10 customers</td>
    </tr>
    <tr>
      <td><code>top_100</code></td>
      <td><span class="text-purple-600 font-mono text-sm">object</span></td>
      <td>MRR, percentage, and count for top 100 customers</td>
    </tr>
    <tr>
      <td><code>rest</code></td>
      <td><span class="text-purple-600 font-mono text-sm">object</span></td>
      <td>MRR, percentage, and count for remaining customers</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Summary Object</td>
    </tr>
    <tr>
      <td><code>total_mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Total MRR across all customers (cents)</td>
    </tr>
    <tr>
      <td><code>total_customers</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Total number of active customers</td>
    </tr>
    <tr>
      <td><code>avg_mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Average MRR per customer (cents)</td>
    </tr>
    <tr>
      <td><code>median_mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Median MRR per customer (cents)</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get concentration analysis**
```bash
curl https://api.growpanel.io/reports/customer-concentration \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get pareto chart data only**
```bash
curl "https://api.growpanel.io/reports/customer-concentration?chart=pareto" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Search for specific customer**
```bash
curl "https://api.growpanel.io/reports/customer-concentration?q=acme" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by region**
```bash
curl "https://api.growpanel.io/reports/customer-concentration?region=us" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Divide by 100 for display in most currencies.</p>
</div>

- **Pareto principle**: Typically 80% of revenue comes from 20% of customers
- **Top 10 detail**: The top 10 customers are listed individually, then grouped (11-20, 21-50, etc.)
- **Concentration risk**: High concentration (e.g., top 5 customers = 50%+ of MRR) indicates risk
- **Median vs average**: Large difference suggests high concentration
- **Use cases**: Investor due diligence, risk assessment, account management prioritization

### Related endpoints

- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - Overall metric snapshots
- [Map](/developers/rest-api/reference/reports/map/) - Geographic distribution
- [MRR Table](/developers/rest-api/reference/reports/mrr-table/) - Time-series MRR data

---

## MRR reports
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/ -->

Endpoints for **MRR**, **churn**, and **segmentation** reports.

---

## MRR

| Endpoint | Description |
|----------|-------------|
| [GET /reports/summary](/developers/rest-api/reference/reports/summary/) | Key SaaS metrics snapshot |
| [GET /reports/mrr](/developers/rest-api/reference/reports/mrr/) | MRR timeline with movements |
| [GET /reports/cmrr-summary](/developers/rest-api/reference/reports/cmrr-summary/) | Committed MRR summary |
| [GET /reports/movement-table](/developers/rest-api/reference/reports/movement-table/) | Individual MRR movements |

## Churn

| Endpoint | Description |
|----------|-------------|
| [GET /reports/cohort](/developers/rest-api/reference/reports/cohort/) | Cohort retention analysis |
| [GET /reports/churn-scheduled](/developers/rest-api/reference/reports/churn-scheduled/) | Scheduled churn forecast |
| [GET /reports/churn-scheduled-movements](/developers/rest-api/reference/reports/churn-scheduled-movements/) | Scheduled churn customer detail |
| [GET /reports/churn-scheduled-summary](/developers/rest-api/reference/reports/churn-scheduled-summary/) | Scheduled churn summary metrics |

## Segmentation

| Endpoint | Description |
|----------|-------------|
| [GET /reports/map](/developers/rest-api/reference/reports/map/) | World map |
| [GET /reports/customer-concentration](/developers/rest-api/reference/reports/customer-concentration/) | Customer concentration analysis |
| [GET /reports/custom-variables](/developers/rest-api/reference/reports/custom-variables/) | Custom variable values for filtering |

---

## World map
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/map -->

The `/reports/map` endpoint returns a geographic breakdown of customers and MRR by country, including key metrics per country. This is ideal for building geographic visualizations and understanding regional performance.

> 💡 **Use case**: Build interactive maps, analyze regional performance, identify expansion opportunities, compare metrics across countries.

## GET /reports/map

Returns country-level metrics for geographic analysis.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/map \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Date range. Format: <code>YYYYMMDD-YYYYMMDD</code> or shortcuts.</td>
    </tr>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency.</td>
    </tr>
    <tr>
      <td><code>sort</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort field. Defaults to <code>current_mrr</code>.</td>
    </tr>
    <tr>
      <td><code>order</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort direction: <code>asc</code> or <code>desc</code>. Defaults to <code>desc</code>.</td>
    </tr>
    <tr>
      <td><code>fix_fx</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">boolean</span></td>
      <td>Use fixed exchange rates.</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>channel</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by channel (space-separated).</td>
    </tr>
    <tr>
      <td><code>size</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer size (space-separated).</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns metrics grouped by country (ISO 3166-1 alpha-2 codes).

```json
{
  "result": {
    "list": {
      "US": {
        "current_mrr": 65000,
        "subscribers": 120,
        "arpa": 542,
        "asp": 800,
        "customer_churn_rate": 0.03,
        "net_mrr_churn": -0.01,
        "ltv": 18000,
        "leads": 200,
        "leads_converted": 50,
        "lead_conversion_rate": 25.0,
        "new_trials": 80,
        "trials_converted": 40,
        "trial_conversion_rate": 50.0,
        "payment_failure_rate": 2.5,
        "mrr_percent": 52.0,
        "subscribers_percent": 48.0,
        "leads_percent": 40.0,
        "trials_percent": 42.1
      },
      "DE": {
        "current_mrr": 25000,
        "subscribers": 60,
        "arpa": 417,
        "asp": 600,
        "customer_churn_rate": 0.02,
        "net_mrr_churn": 0.005,
        "ltv": 20850,
        "leads": 100,
        "leads_converted": 30,
        "lead_conversion_rate": 30.0,
        "new_trials": 50,
        "trials_converted": 25,
        "trial_conversion_rate": 50.0,
        "payment_failure_rate": 1.8,
        "mrr_percent": 20.0,
        "subscribers_percent": 24.0,
        "leads_percent": 20.0,
        "trials_percent": 26.3
      }
    }
  }
}
```

### Response fields (per country)

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Revenue Metrics</td>
    </tr>
    <tr>
      <td><code>current_mrr</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR in base currency (cents)</td>
    </tr>
    <tr>
      <td><code>subscribers</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Active subscriber count</td>
    </tr>
    <tr>
      <td><code>arpa</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Average revenue per account (cents)</td>
    </tr>
    <tr>
      <td><code>asp</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Average subscription price (cents)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Retention Metrics</td>
    </tr>
    <tr>
      <td><code>customer_churn_rate</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Customer churn rate (decimal, e.g., 0.03 = 3%)</td>
    </tr>
    <tr>
      <td><code>net_mrr_churn</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Net MRR churn rate (decimal)</td>
    </tr>
    <tr>
      <td><code>ltv</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Customer lifetime value (cents)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Lead Metrics</td>
    </tr>
    <tr>
      <td><code>leads</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Total leads</td>
    </tr>
    <tr>
      <td><code>leads_converted</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Leads converted to paid</td>
    </tr>
    <tr>
      <td><code>lead_conversion_rate</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Lead conversion rate (percentage)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Trial Metrics</td>
    </tr>
    <tr>
      <td><code>new_trials</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Total new trials</td>
    </tr>
    <tr>
      <td><code>trials_converted</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Trials converted to paid</td>
    </tr>
    <tr>
      <td><code>trial_conversion_rate</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Trial conversion rate (percentage)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Other Metrics</td>
    </tr>
    <tr>
      <td><code>payment_failure_rate</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Payment failure rate (percentage)</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Distribution Percentages</td>
    </tr>
    <tr>
      <td><code>mrr_percent</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage of total MRR</td>
    </tr>
    <tr>
      <td><code>subscribers_percent</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage of total subscribers</td>
    </tr>
    <tr>
      <td><code>leads_percent</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage of total leads</td>
    </tr>
    <tr>
      <td><code>trials_percent</code></td>
      <td><span class="text-purple-600 font-mono text-sm">float</span></td>
      <td>Percentage of total trials</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get geographic distribution**
```bash
curl https://api.growpanel.io/reports/map \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Sort by subscriber count**
```bash
curl "https://api.growpanel.io/reports/map?sort=subscribers&order=desc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by region**
```bash
curl "https://api.growpanel.io/reports/map?region=eu" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Compare specific countries**
```bash
curl "https://api.growpanel.io/reports/map?region=us gb de" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Divide by 100 for display in most currencies.</p>
</div>

- **Country codes**: Uses ISO 3166-1 alpha-2 codes (e.g., US, GB, DE)
- **Geographic source**: Based on customer billing address from your billing system
- **Percentage totals**: Distribution percentages show each country's share of the total
- **Missing countries**: Countries with zero customers/MRR are not included in response
- **Sorting**: Default sort is by `current_mrr` descending (highest revenue first)

### Related endpoints

- [Summary Metrics](/developers/rest-api/reference/reports/summary/) - Overall metric snapshots
- [MRR Table](/developers/rest-api/reference/reports/mrr-table/) - Time-series with country breakdown
- [Customer Concentration](/developers/rest-api/reference/reports/customer-concentration/) - Revenue concentration analysis

---

## Movement table
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/movement-table -->

The `/reports/movement-table` endpoint returns a detailed list of individual MRR movements (new, expansion, contraction, churn, reactivation) for a given period. Each movement includes customer details, amounts, and optional line-level breakdowns.

> 💡 **Use case**: Investigate specific MRR changes, audit movements, export detailed transaction data. Essential for understanding which customers drove revenue changes.

## GET /reports/movement-table

Returns a list of individual movements with customer-level detail.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/movement-table \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Date range. Format: <code>YYYYMMDD-YYYYMMDD</code> or shortcuts like <code>last-12-months</code>. Defaults to last 365 days.</td>
    </tr>
    <tr>
      <td><code>interval</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Aggregation interval: <code>day</code>, <code>week</code>, <code>month</code>, <code>quarter</code>, <code>year</code>. Defaults to <code>month</code>.</td>
    </tr>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Target currency for conversion. Defaults to account base currency.</td>
    </tr>
    <tr>
      <td><code>selected-date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter movements to a specific period start date (format: <code>YYYY-MM-DD</code>).</td>
    </tr>
    <tr>
      <td><code>selected-type</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by movement type: <code>new</code>, <code>expansion</code>, <code>contraction</code>, <code>churn</code>, <code>reactivation</code></td>
    </tr>
    <tr>
      <td><code>breakdown</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Group by dimension (e.g., <code>plan</code>, <code>country</code>).</td>
    </tr>
    <tr>
      <td><code>breakdown-value</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter to a specific breakdown value when using breakdown parameter.</td>
    </tr>
    <tr>
      <td><code>committed</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Set to <code>true</code> to show committed/future movements instead of actual.</td>
    </tr>
    <tr>
      <td><code>fix_fx</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">boolean</span></td>
      <td>Use fixed exchange rates from start date.</td>
    </tr>
    <tr>
      <td><code>sort</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort field (e.g., <code>mrr_change</code>, <code>date</code>, <code>customer_name</code>).</td>
    </tr>
    <tr>
      <td><code>order</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Sort direction: <code>asc</code> or <code>desc</code>. Defaults to <code>desc</code>.</td>
    </tr>
    <tr>
      <td><code>customer</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer ID to show detailed line items for that customer.</td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by region or country codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by currency codes (space-separated).</td>
    </tr>
    <tr>
      <td><code>plan</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by plan group IDs (space-separated).</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by industry (space-separated).</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (space-separated).</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a list of movements with customer details.

```json
{
  "result": {
    "list": [
      {
        "date": "2025-01-15",
        "currency": "usd",
        "customer_id": "cus_123",
        "customer_name": "Acme Corp",
        "customer_email": "billing@acme.com",
        "type": "expansion",
        "description": "Pro Plan → Enterprise Plan",
        "mrr_change": 5000,
        "mrr_change_base_currency": 5000,
        "customer_count_change": 0,
        "quantity_change": 0
      },
      {
        "date": "2025-01-20",
        "currency": "eur",
        "customer_id": "cus_456",
        "customer_name": "Beta LLC",
        "customer_email": "admin@beta.com",
        "type": "new",
        "description": "Pro Plan",
        "mrr_change": 4900,
        "mrr_change_base_currency": 5290,
        "customer_count_change": 1,
        "quantity_change": 1
      }
    ]
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Date of the movement (ISO format: YYYY-MM-DD)</td>
    </tr>
    <tr>
      <td><code>currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Original currency of the movement</td>
    </tr>
    <tr>
      <td><code>customer_id</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer external ID from billing system</td>
    </tr>
    <tr>
      <td><code>customer_name</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer name</td>
    </tr>
    <tr>
      <td><code>customer_email</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Customer email address</td>
    </tr>
    <tr>
      <td><code>type</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Movement type: <code>new</code>, <code>expansion</code>, <code>contraction</code>, <code>churn</code>, <code>reactivation</code></td>
    </tr>
    <tr>
      <td><code>description</code></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Human-readable description of the change</td>
    </tr>
    <tr>
      <td><code>mrr_change</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR change in original currency (cents, negative for churn/contraction)</td>
    </tr>
    <tr>
      <td><code>mrr_change_base_currency</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR change converted to base currency (cents)</td>
    </tr>
    <tr>
      <td><code>customer_count_change</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Customer count change (-1 for churn, 1 for new, 0 for expansion/contraction)</td>
    </tr>
    <tr>
      <td><code>quantity_change</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Seat/quantity change (for usage-based or per-seat plans)</td>
    </tr>
  </tbody>
</table>

### Line-level detail

When filtering by `customer` parameter, an additional `lines` array is included with invoice-level detail:

```json
{
  "result": {
    "list": [
      {
        "date": "2025-01-15",
        "customer_id": "cus_123",
        "type": "expansion",
        "mrr_change": 5000,
        "lines": [
          {
            "description": "Enterprise Plan",
            "mrr": 10000,
            "quantity": 1
          },
          {
            "description": "Pro Plan (removed)",
            "mrr": -5000,
            "quantity": -1
          }
        ]
      }
    ]
  }
}
```

### Example requests

<div class="mt-6 space-y-4">

**Get all movements for January 2025**
```bash
curl "https://api.growpanel.io/reports/movement-table?date=20250101-20250131" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get only expansion movements**
```bash
curl "https://api.growpanel.io/reports/movement-table?selected-type=expansion" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get movements for a specific period**
```bash
curl "https://api.growpanel.io/reports/movement-table?selected-date=2025-01-01&interval=month" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Get detailed lines for a customer**
```bash
curl "https://api.growpanel.io/reports/movement-table?customer=cus_123" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Sort by largest MRR changes**
```bash
curl "https://api.growpanel.io/reports/movement-table?sort=mrr_change&order=desc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Divide by 100 for display in most currencies.</p>
</div>

- **Movement types**: Each movement represents a discrete change in customer MRR
- **Negative values**: Churn and contraction have negative `mrr_change` values
- **Date alignment**: Movements are timestamped to the interval start date
- **Customer filtering**: Use `customer` parameter to drill into specific customer changes
- **Committed mode**: Set `committed=true` to see future scheduled movements

### Related endpoints

- [MRR Timeline](/developers/rest-api/reference/reports/mrr/) - Aggregated movement summary
- [MRR Table](/developers/rest-api/reference/reports/mrr-table/) - Time-series metrics
- [Scheduled Churn Movements](/developers/rest-api/reference/reports/churn-scheduled-movements/) - Future churn detail

---

## MRR timeline
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/mrr -->

Get a detailed timeline of Monthly Recurring Revenue (MRR) and customer movements for your account. You can optionally break down the data by plan, currency, billing frequency, pricing model, customer subtype, region/market, country, industry, customer age, or size. The report also calculates churn, retention, ARPA, ASP, LTV, customer lifetime, quick ratio, and FX adjustments.

## GET /reports/mrr

### Query parameters

| Parameter         | Type      | Description |
| ---------------- | -------- | ----------- |
| date             | string   | Optional date range for the report (e.g., `20250901-20251001`). Defaults to last 365 days. |
| interval         | string   | `day`, `week`, `quarter`, or `month`. Defaults to `month`. |
| breakdown        | string   | Group MRR by `plan`, `currency`, `billing_freq`, `pricing_model`, `payment_method`, `subtype`, `market`, `country`, `industry`, `age`, `size`. |
| baseCurrency     | string   | Optional base currency for FX conversion. Defaults to the account's base currency. |
| customer         | string   | Filter by a specific customer ID. |
| plan             | string   | Filter by plan IDs (space-separated for multiple). |
| currency         | string   | Filter by currency codes (space-separated). |
| billing_freq     | string   | Filter by billing frequency (month/year). |
| pricing_model    | string   | Filter by pricing model (`licensed`, `metered`). |
| payment_method   | string   | Filter by payment method (e.g., `visa`, `paypal`, `ach`). |
| subtype          | string   | Filter by customer subtype. |
| region           | string   | Filter by region (maps to countries). |
| country          | string   | Filter by specific country codes. |
| industry         | string   | Filter by customer industry. |
| age              | string   | Filter by customer age in months or ranges (e.g., `0-6 6-12`). |
| size             | string   | Filter by customer size. |
| status           | string   | Filter by subscription status. |
| category         | string   | Filter by MRR movement category (`new`, `expansion`, `contraction`, `churn`, `reactivation`). |
| fix_fx           | boolean  | If `true`, uses a fixed FX rate from the start of the date range instead of period-specific rates. This is useful for analyzing growth without FX fluctuations affecting the numbers. |
| fx_date          | string   | Optional date to use for the fixed FX rate when `fix_fx=true` (e.g., `20251231` or `2025-12-31`). Defaults to the start of the date range. Use this to compare reports with consistent FX rates across different date ranges. |

### Example response

```json
200 OK
{
  "currency": "usd",
  "breakdown": "plan",
  "result": [
    {
      "date": "2025-09-01",
      "end_date": "2025-09-30",
      "new": 5000,
      "expansion": 1000,
      "contraction": -500,
      "churn": -200,
      "reactivation": 100,
      "mrr_diff": 5400,
      "customers_diff": 5,
      "total_mrr": 10500,
      "total_arr": 126000,
      "total_customers": 50,
      "arpa": 210,
      "asp": 1000,
      "quick_ratio": 2.5,
      "customer_churn_rate": 4,
      "mrr_churn_rate": 2,
      "net_mrr_churn_rate": 1,
      "customer_retention_rate": 96,
      "mrr_retention_rate": 98,
      "nrr": 99,
      "customer_churn_avg": 3.5,
      "ltv": 5250,
      "customer_lifetime": 28.6,
      "fx_adjustment": 50,
      "breakdown": {
        "basic": {
          "label": "Basic Plan",
          "new": 2000,
          "expansion": 500,
          "contraction": -100,
          "churn": -50,
          "reactivation": 0,
          "mrr_diff": 2350,
          "customers_diff": 2,
          "total_mrr": 5000,
          "total_arr": 60000,
          "total_customers": 25,
          "arpa": 200,
          "asp": 1000,
          "customer_churn_rate": 2,
          "customer_churn_avg": 1.8,
          "ltv": 10000,
          "customer_lifetime": 55.6,
          "fx_adjustment": 20
        },
        "pro": {
          "label": "Pro Plan",
          "...": "..."
        }
      }
    }
  ]
}
````

### Result properties

| Property                | Type    | Description                                                        |
| ----------------------- | ------- | ------------------------------------------------------------------ |
| date                    | string  | Start of the period (yyyy-MM-dd).                                  |
| end_date                | string  | End of the period.                                                 |
| new                     | integer | MRR from new customers.                                            |
| expansion               | integer | MRR from existing customers upgrading.                             |
| contraction             | integer | MRR lost from downgrades.                                          |
| churn                   | integer | MRR lost from churned customers.                                   |
| reactivation            | integer | MRR from reactivated customers.                                    |
| mrr_diff                | integer | Total MRR movement for the period.                                 |
| customers_diff          | integer | Total customer movement for the period.                            |
| total_mrr               | integer | Total MRR in base currency at period end.                          |
| total_arr               | integer | Annualized recurring revenue (MRR × 12).                           |
| total_customers         | integer | Total customers at period end.                                     |
| arpa                    | integer | Average revenue per account.                                       |
| asp                     | integer | Average subscription price for new customers.                      |
| quick_ratio             | float   | Ratio of growth (new + expansion) to losses (contraction + churn). |
| customer_churn_rate     | float   | Customer churn rate for the period (percentage, e.g., 4 = 4%).     |
| mrr_churn_rate          | float   | MRR churn rate for the period (percentage).                        |
| net_mrr_churn_rate      | float   | Net MRR churn rate (percentage).                                   |
| customer_retention_rate | float   | 100% - customer churn rate.                                        |
| mrr_retention_rate      | float   | 100% - MRR churn rate.                                             |
| nrr                     | float   | Net revenue retention.                                             |
| customer_churn_avg      | float   | Average customer churn rate over past 6 periods (percentage).      |
| ltv                     | integer | Lifetime value estimate based on ARPA / average monthly churn.     |
| customer_lifetime       | float   | Average customer lifetime in months (1 / average monthly churn).   |
| fx_adjustment           | integer | FX rate adjustment applied to MRR.                                 |

### Breakdown properties

If `breakdown` is used, the `breakdown` object contains keys corresponding to breakdown values (plan IDs, currency codes, countries, etc.) with the following structure:

| Property               | Type    | Description                             |
| ---------------------- | ------- | --------------------------------------- |
| label                  | string  | Display label for the breakdown value.  |
| total_mrr              | integer | Total MRR for this breakdown.           |
| total_arr              | integer | Total ARR for this breakdown.           |
| total_customers        | integer | Total customers in this breakdown.      |
| new                    | integer | MRR from new customers.                 |
| expansion              | integer | MRR from upgrades.                      |
| contraction            | integer | MRR lost from downgrades.               |
| churn                  | integer | MRR lost from churn.                    |
| reactivation           | integer | MRR from reactivations.                 |
| mrr_diff               | integer | Net MRR movement.                       |
| customers_diff         | integer | Net customer movement.                  |
| new_customers          | integer | Number of new customers.                |
| expansion_customers    | integer | Number of customers expanding.          |
| contraction_customers  | integer | Number of customers contracting.        |
| churn_customers        | integer | Number of churned customers.            |
| reactivation_customers | integer | Number of reactivated customers.        |
| arpa                   | integer | Average revenue per account.            |
| asp                    | integer | Average subscription price.             |
| customer_churn_rate    | float   | Customer churn rate (percentage).       |
| customer_churn_avg     | float   | Avg churn over prior periods (%).       |
| ltv                    | integer | Lifetime value estimate.                |
| customer_lifetime      | float   | Average customer lifetime in months.    |
| fx_adjustment          | integer | FX adjustment for this breakdown.       |

---

## Summary Metrics
<!-- url: https://growpanel.io/developers/rest-api/reference/reports/summary -->

Get a snapshot of your key SaaS metrics with current values and percentage changes over 30, 60, 180, and 365-day periods. This endpoint provides a quick overview of MRR, ARR, subscriber count, and ARPA trends.

> 💡 **Use case**: Perfect for dashboard widgets, executive summaries, and trend analysis. Returns pre-calculated metrics for fast loading.

## GET /reports/summary

Returns current metrics and historical comparisons for MRR, ARR, subscribers, and ARPA.

### Authentication

<span class="inline-block bg-gray-100 text-gray-800 text-xs font-mono px-2 py-1 rounded">Required</span>

Include your API key in the Authorization header:

```bash
curl https://api.growpanel.io/reports/summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Query parameters

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Parameter</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>date</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Date range for historical context. Format: <code>YYYYMMDD-YYYYMMDD</code> or shortcuts like <code>last-12-months</code>. Defaults to last 365 days.</td>
    </tr>
    <tr>
      <td><code>currency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by specific currency codes (space-separated for multiple). Example: <code>usd eur gbp</code></td>
    </tr>
    <tr>
      <td><code>region</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by geographic region. Options: <code>nordics</code>, <code>eu</code>, <code>emea</code>, <code>apac</code>, <code>latam</code>, <code>north_america</code>, <code>dach</code></td>
    </tr>
    <tr>
      <td><code>plan</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by plan group IDs (space-separated for multiple).</td>
    </tr>
    <tr>
      <td><code>baseCurrency</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Currency for reporting. Defaults to your account's base currency (e.g., <code>usd</code>).</td>
    </tr>
    <tr>
      <td><code>fix_fx</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">boolean</span></td>
      <td>If <code>true</code>, uses fixed exchange rates from the start date instead of period-specific rates.</td>
    </tr>
    <tr>
      <td><code>billing_freq</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by billing frequency: <code>month</code>, <code>year</code>, <code>quarter</code>, <code>week</code></td>
    </tr>
    <tr>
      <td><code>payment_method</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by payment method (e.g., <code>card</code>, <code>ach</code>, <code>paypal</code>)</td>
    </tr>
    <tr>
      <td><code>pricing_model</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by pricing model: <code>licensed</code> or <code>metered</code></td>
    </tr>
    <tr>
      <td><code>age</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer age in months. Use ranges like <code>0-6</code>, <code>6-12</code>, or <code>12-</code> for 12+ months</td>
    </tr>
    <tr>
      <td><code>industry</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by customer industry (uses custom variables)</td>
    </tr>
    <tr>
      <td><code>data_source</code><span class="text-gray-400 text-xs ml-1">optional</span></td>
      <td><span class="text-purple-600 font-mono text-sm">string</span></td>
      <td>Filter by data source ID (e.g., specific Stripe account)</td>
    </tr>
  </tbody>
</table>

### Response

<span class="inline-block bg-green-100 text-green-800 text-xs font-semibold px-2 py-1 rounded">200 OK</span>

Returns a `summary` object containing current metrics and historical comparisons.

```json
{
  "summary": {
    "mrr_current": 125000,
    "mrr_30": 120000,
    "mrr_60": 115000,
    "mrr_180": 100000,
    "mrr_365": 85000,
    "arr_current": 1500000,
    "arr_30": 1440000,
    "arr_60": 1380000,
    "arr_180": 1200000,
    "arr_365": 1020000,
    "subscribers_current": 250,
    "subscribers_30": 240,
    "subscribers_60": 230,
    "subscribers_180": 200,
    "subscribers_365": 170,
    "arpa_current": 500,
    "arpa_30": 500,
    "arpa_60": 500,
    "arpa_180": 500,
    "arpa_365": 500,
    "mrr_percentage_change_30": 4.17,
    "mrr_percentage_change_60": 8.70,
    "mrr_percentage_change_180": 25.00,
    "mrr_percentage_change_365": 47.06,
    "arr_percentage_change_30": 4.17,
    "arr_percentage_change_60": 8.70,
    "arr_percentage_change_180": 25.00,
    "arr_percentage_change_365": 47.06,
    "subscribers_percentage_change_30": 4.17,
    "subscribers_percentage_change_60": 8.70,
    "subscribers_percentage_change_180": 25.00,
    "subscribers_percentage_change_365": 47.06,
    "arpa_percentage_change_30": 0.00,
    "arpa_percentage_change_60": 0.00,
    "arpa_percentage_change_180": 0.00,
    "arpa_percentage_change_365": 0.00
  }
}
```

### Response fields

<table class="w-full">
  <thead>
    <tr>
      <th class="text-left">Field</th>
      <th class="text-left">Type</th>
      <th class="text-left">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">MRR Metrics</td>
    </tr>
    <tr>
      <td><code>mrr_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Current Monthly Recurring Revenue in base currency (cents)</td>
    </tr>
    <tr>
      <td><code>mrr_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR from 30 days ago</td>
    </tr>
    <tr>
      <td><code>mrr_60</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR from 60 days ago</td>
    </tr>
    <tr>
      <td><code>mrr_180</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR from 180 days ago</td>
    </tr>
    <tr>
      <td><code>mrr_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>MRR from 365 days ago</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">ARR Metrics</td>
    </tr>
    <tr>
      <td><code>arr_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Current Annual Recurring Revenue (MRR × 12)</td>
    </tr>
    <tr>
      <td><code>arr_30</code> through <code>arr_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Historical ARR values at 30, 60, 180, and 365 days ago</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Subscriber Metrics</td>
    </tr>
    <tr>
      <td><code>subscribers_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Current active subscriber count</td>
    </tr>
    <tr>
      <td><code>subscribers_30</code> through <code>subscribers_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">integer</span></td>
      <td>Historical subscriber counts at 30, 60, 180, and 365 days ago</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">ARPA Metrics</td>
    </tr>
    <tr>
      <td><code>arpa_current</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Current Average Revenue Per Account (MRR / subscribers)</td>
    </tr>
    <tr>
      <td><code>arpa_30</code> through <code>arpa_365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Historical ARPA values at 30, 60, 180, and 365 days ago</td>
    </tr>
    <tr>
      <td colspan="3" class="bg-gray-50 font-semibold text-sm">Percentage Changes</td>
    </tr>
    <tr>
      <td><code>mrr_percentage_change_30</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Percentage change in MRR over 30 days. Positive indicates growth.</td>
    </tr>
    <tr>
      <td><code>*_percentage_change_60/180/365</code></td>
      <td><span class="text-purple-600 font-mono text-sm">number</span></td>
      <td>Percentage changes over 60, 180, and 365 day periods for MRR, ARR, subscribers, and ARPA</td>
    </tr>
  </tbody>
</table>

### Example requests

<div class="mt-6 space-y-4">

**Get overall summary**
```bash
curl https://api.growpanel.io/reports/summary \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by region**
```bash
curl "https://api.growpanel.io/reports/summary?region=eu" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Filter by plan and currency**
```bash
curl "https://api.growpanel.io/reports/summary?plan=plan_123&currency=usd" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Use fixed exchange rates**
```bash
curl "https://api.growpanel.io/reports/summary?fix_fx=true&baseCurrency=eur" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

</div>

### Errors

<div class="space-y-3 mt-6">

<span class="inline-block bg-red-100 text-red-800 text-xs font-semibold px-2 py-1 rounded">401 Unauthorized</span>

Invalid or missing API key.

```json
{
  "error": "Unauthorized"
}
```

<span class="inline-block bg-red-100 text-red-800 text-xs font-semibold px-2 py-1 rounded">500 Internal Server Error</span>

Server error occurred while processing the request.

```json
{
  "error": "Internal server error"
}
```

</div>

### Notes

<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 my-6">
  <p class="text-sm"><strong>⚠️ Currency values:</strong> All monetary values are returned in cents/smallest currency unit. Divide by 100 for display in most currencies.</p>
</div>

- **Historical data**: Comparisons are calculated from fixed points in time (30, 60, 180, 365 days ago from today)
- **Percentage changes**: Calculated as `((current - historical) / historical) * 100`
- **Active subscribers**: Only includes customers with active subscriptions (excludes churned, leads, and trials without payment)
- **ARPA calculation**: Computed as total MRR divided by total active subscribers
- **Exchange rates**: Applied daily unless `fix_fx=true` is specified
- **Filtering**: All filter parameters work together (AND logic) to narrow down results
- **Performance**: This endpoint is optimized for dashboard use with pre-calculated aggregates

### Related endpoints

- [MRR Timeline](/developers/rest-api/reference/reports/mrr/) - Detailed MRR breakdown over time
- [Churn Scheduled](/developers/rest-api/reference/reports/churn-scheduled/) - Future churn predictions
- [Cohort Analysis](/developers/rest-api/reference/reports/cohort/) - Customer retention by cohort

---

## HubSpot Settings
<!-- url: https://growpanel.io/developers/rest-api/reference/settings/hubspot -->

Retrieve HubSpot integration settings for the authenticated account.

---

## GET /settings/hubspot

Returns the current HubSpot connection status and sync configuration.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/settings/hubspot \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "connected": true,
  "portal_id": "12345678",
  "portal_name": "Acme Corp",
  "connected_at": "2024-08-01T14:00:00Z",
  "sync_enabled": true,
  "sync_direction": "growpanel_to_hubspot",
  "last_sync": "2025-01-10T06:00:00Z",
  "properties_mapped": [
    "mrr",
    "plan_name",
    "subscription_status",
    "paid_started"
  ]
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `connected` | boolean | Whether HubSpot is connected |
| `portal_id` | string | HubSpot portal ID |
| `portal_name` | string | HubSpot portal name |
| `connected_at` | string | When the connection was established |
| `sync_enabled` | boolean | Whether automatic sync is enabled |
| `sync_direction` | string | Direction of data sync |
| `last_sync` | string | When data was last synchronized |
| `properties_mapped` | array | List of GrowPanel properties synced to HubSpot |

---

## Notes

- HubSpot connections are managed via OAuth in the GrowPanel web interface
- To connect or configure HubSpot, visit **Settings → Integrations**
- See [HubSpot integration](/docs/integrations/hubspot/) for setup instructions

---

## Settings API
<!-- url: https://growpanel.io/developers/rest-api/reference/settings/ -->

The **Settings API** allows you to configure integrations, notifications, and other account settings programmatically.

---

## Endpoints

| Endpoint | Description |
|----------|-------------|
| [GET /settings/notifications](/developers/rest-api/reference/settings/notifications/) | Get notification preferences |
| [PUT /settings/notifications](/developers/rest-api/reference/settings/notifications/) | Update notification settings |
| [GET /settings/stripe](/developers/rest-api/reference/settings/stripe/) | Get Stripe integration settings |
| [GET /settings/hubspot](/developers/rest-api/reference/settings/hubspot/) | Get HubSpot integration settings |

---

## Authentication

All Settings API endpoints require an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/settings/notifications \
  -H "Authorization: Bearer YOUR_API_KEY"
```

---

## Related pages

- [Notifications settings](/docs/integrations/notifications/) - Configure in the UI
- [Data sources](/docs/data-sources/) - Setting up integrations

---

## Notification Settings
<!-- url: https://growpanel.io/developers/rest-api/reference/settings/notifications -->

Retrieve and update notification preferences for the authenticated account.

---

## GET /settings/notifications

Returns current notification settings.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/settings/notifications \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "email": {
    "enabled": true,
    "recipients": ["admin@acme.com", "finance@acme.com"],
    "frequency": "weekly"
  },
  "slack": {
    "enabled": true,
    "channel": "#revenue-updates",
    "events": ["new_customer", "churn", "expansion"]
  },
  "alerts": {
    "churn_threshold": 5,
    "mrr_drop_threshold": 10
  }
}
```

---

## PUT /settings/notifications

Update notification preferences.

### Request

```bash
curl -X PUT https://api.growpanel.io/v1/settings/notifications \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": {
      "enabled": true,
      "frequency": "daily"
    },
    "alerts": {
      "churn_threshold": 3
    }
  }'
```

### Response

**Status:** 200 OK

Returns the updated notification settings.

---

## Related pages

- [Notifications](/docs/integrations/notifications/) - Setting up notifications
- [Slack integration](/docs/integrations/slack/) - Connecting Slack

---

## Stripe Settings
<!-- url: https://growpanel.io/developers/rest-api/reference/settings/stripe -->

Retrieve Stripe integration settings for the authenticated account.

---

## GET /settings/stripe

Returns the current Stripe connection status and configuration.

### Authentication

Requires an API key with **admin** access level.

```bash
curl https://api.growpanel.io/v1/settings/stripe \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Response

**Status:** 200 OK

```json
{
  "connected": true,
  "account_id": "acct_1ABC123",
  "account_name": "Acme Corp",
  "livemode": true,
  "connected_at": "2024-06-15T10:00:00Z",
  "last_sync": "2025-01-10T08:00:00Z",
  "sync_status": "complete",
  "customers_imported": 250,
  "invoices_imported": 3500
}
```

### Response fields

| Field | Type | Description |
|-------|------|-------------|
| `connected` | boolean | Whether Stripe is connected |
| `account_id` | string | Stripe account ID |
| `account_name` | string | Stripe account display name |
| `livemode` | boolean | Whether connected to live (not test) mode |
| `connected_at` | string | When the connection was established |
| `last_sync` | string | When data was last synchronized |
| `sync_status` | string | Current sync status (syncing, complete, error) |
| `customers_imported` | integer | Number of customers imported |
| `invoices_imported` | integer | Number of invoices imported |

---

## Notes

- Stripe connections are managed via OAuth in the GrowPanel web interface
- To connect or disconnect Stripe, visit **Settings → Data Sources**
- See [Stripe integration](/docs/data-sources/stripe/) for setup instructions

---
