> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appeeky.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription Metrics (MRR & Churn)

> SaaS-grade subscription health for your iOS apps — MRR, ARR, ARPU, churn, trial conversion — derived from App Store Connect reports and FX-converted to USD

The Subscription Metrics endpoint returns the SaaS metrics App Store Connect doesn't show out of the box: **monthly recurring revenue (MRR), ARR, ARPU, churn rate, trial conversion rate**, and the daily event counts (new, canceled, refunded, reactivated, expired) behind them.

We compute these from Apple's `SUBSCRIPTION` and `SUBSCRIPTION_EVENT` reports, normalize all proceeds to a monthly basis, and convert every currency to USD using historical exchange rates — so a yearly subscription priced in EUR contributes the right MRR amount on the day it was sold.

<Note>
  **Requires connected ASC account.** Connect your App Store Connect API key and Vendor Number in [appeeky.com → Settings → Integrations](https://appeeky.com). Subscription reports refresh daily and right after you connect.
</Note>

<Info>
  **Pro feature** — requires Indie plan or higher.
</Info>

***

## Get Subscription Metrics

```
GET /v1/connect/metrics/subscriptions
```

Returns headline totals, per-app breakdown, and a daily time series for the requested window.

### Query parameters

| Name    | Type   | Default     | Description                                                                                                                        |
| ------- | ------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `from`  | string | 30 days ago | Start date `YYYY-MM-DD`.                                                                                                           |
| `to`    | string | today       | End date `YYYY-MM-DD`.                                                                                                             |
| `appId` | string | —           | Filter to one App Store Connect app ID. Omit to roll up across all your apps (MRR is summed, churn is paying-subscriber-weighted). |

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl "https://api.appeeky.com/v1/connect/metrics/subscriptions?from=2026-03-25&to=2026-04-24" \
    -H "X-API-Key: apk_your_key_here"
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const params = new URLSearchParams({
    from: "2026-03-25",
    to: "2026-04-24",
    appId: "6759740679",
  });
  const res = await fetch(
    `https://api.appeeky.com/v1/connect/metrics/subscriptions?${params}`,
    { headers: { "X-API-Key": process.env.APEEKY_KEY } }
  );
  const { data } = await res.json();
  ```
</CodeGroup>

**Response (200 OK):**

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": {
    "from": "2026-03-25",
    "to": "2026-04-24",
    "appId": null,

    "totals": {
      "mrr_usd": 12480.55,
      "mrr_delta_pct": 0.0832,
      "arr_usd": 149766.60,
      "paying_subscribers": 1842,
      "arpu_usd": 6.7755,
      "avg_churn_rate": 0.041200,
      "trial_conversion_rate": 0.3620,
      "new_subscriptions": 612,
      "canceled_subscriptions": 487,
      "refunded_subscriptions": 19,
      "trial_starts": 2280,
      "trial_conversions": 825,
      "expired_subscriptions": 102
    },

    "apps": [
      {
        "appId": "6759740679",
        "appName": "Voice Tape Record",
        "iconUrl": "https://is1-ssl.mzstatic.com/image/.../icon.png",
        "mrr_usd": 8920.30,
        "arpu_usd": 7.1240,
        "paying_subscribers": 1252,
        "churn_rate": 0.038500,
        "new_subscriptions_30d": 410,
        "canceled_subscriptions_30d": 318,
        "trial_conversions_30d": 562
      },
      {
        "appId": "6757361049",
        "appName": "NewSub: App Developer Alerts",
        "iconUrl": "https://is1-ssl.mzstatic.com/image/.../icon.png",
        "mrr_usd": 3560.25,
        "arpu_usd": 6.0312,
        "paying_subscribers": 590,
        "churn_rate": 0.046800,
        "new_subscriptions_30d": 202,
        "canceled_subscriptions_30d": 169,
        "trial_conversions_30d": 263
      }
    ],

    "series": [
      {
        "metric_date": "2026-03-25",
        "mrr_usd": 11521.40,
        "arpu_usd": 6.6210,
        "paying_subscribers": 1740,
        "new_subscriptions": 18,
        "canceled_subscriptions": 14,
        "refunded_subscriptions": 0,
        "reactivated_subscriptions": 2,
        "trial_starts": 72,
        "trial_conversions": 24,
        "expired_subscriptions": 4,
        "billing_retries": 5,
        "churn_rate": 0.041800
      }
    ]
  }
}
```

***

## Field reference

### `totals`

Headline numbers across the requested window.

| Field                                                                                                                                 | Description                                                                                                                                                                                                                             |
| ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mrr_usd`                                                                                                                             | **Monthly Recurring Revenue** for the most recent day in the window, in USD. Yearly subs are normalized to `proceeds / 12`, weekly to `proceeds × 4.345`, etc. Includes only paying subscribers (introductory \$0 offers contribute 0). |
| `mrr_delta_pct`                                                                                                                       | Relative change in MRR vs the first day of the window. `0.0832` = +8.32%.                                                                                                                                                               |
| `arr_usd`                                                                                                                             | Annual Run Rate — `mrr_usd × 12`.                                                                                                                                                                                                       |
| `paying_subscribers`                                                                                                                  | Active paying subscribers on the most recent day. Excludes free trials.                                                                                                                                                                 |
| `arpu_usd`                                                                                                                            | Average Revenue Per User — `mrr_usd / paying_subscribers`.                                                                                                                                                                              |
| `avg_churn_rate`                                                                                                                      | Weighted average churn over the window (weighted by `paying_subscribers` so a tiny app with 100% churn doesn't dominate the rate). `0.0412` = 4.12% monthly churn.                                                                      |
| `trial_conversion_rate`                                                                                                               | `trial_conversions / trial_starts` over the window. `0.3620` = 36.2% of trials become paying subs.                                                                                                                                      |
| `new_subscriptions`, `canceled_subscriptions`, `refunded_subscriptions`, `trial_starts`, `trial_conversions`, `expired_subscriptions` | Cumulative event counts in the window.                                                                                                                                                                                                  |

### `apps`

One row per app, sorted by `mrr_usd` descending. Each row is the **latest day's snapshot** for that app, with 30-day rolling event counts. Includes the app's name and icon so dashboards don't need a second round-trip per app.

### `series`

Daily time series ready for charting. When `appId` is omitted, MRR and event counts are **summed across apps**, and churn is paying-subscriber-weighted (not a simple mean — same logic as `totals.avg_churn_rate`).

| Field                       | Description                                                                     |
| --------------------------- | ------------------------------------------------------------------------------- |
| `metric_date`               | ISO date `YYYY-MM-DD`.                                                          |
| `mrr_usd`                   | MRR for that day.                                                               |
| `arpu_usd`                  | `mrr_usd / paying_subscribers` for that day.                                    |
| `paying_subscribers`        | Active paying subscribers on that day.                                          |
| `new_subscriptions`         | New paying subs that day.                                                       |
| `canceled_subscriptions`    | Cancellations (including auto-renew off).                                       |
| `refunded_subscriptions`    | Apple-issued refunds.                                                           |
| `reactivated_subscriptions` | Lapsed users who came back.                                                     |
| `trial_starts`              | New free-trial starts.                                                          |
| `trial_conversions`         | Trials that converted to paying.                                                |
| `expired_subscriptions`     | Subscriptions that lapsed without renewing.                                     |
| `billing_retries`           | Renewals Apple is retrying after a payment failure.                             |
| `churn_rate`                | `canceled_subscriptions / paying_subscribers_yesterday`, rounded to 6 decimals. |

***

## How the numbers are computed

<AccordionGroup>
  <Accordion title="MRR — monthly normalization and FX">
    We download Apple's daily `SUBSCRIPTION` report. For each row, we:

    1. Skip rows with `Active Standard Price Subscriptions = 0` (the user is in a free trial or intro offer).
    2. Normalize `Developer Proceeds` to a monthly basis using the subscription duration:
       * **1 week** → `× 4.345`
       * **1 month** → `× 1`
       * **2 months** → `÷ 2`
       * **3 months** → `÷ 3`
       * **6 months** → `÷ 6`
       * **1 year** → `÷ 12`
    3. Convert the result from the customer's currency to USD using the **historical exchange rate** for that day (Frankfurter, ECB-sourced). A subscription sold in EUR on April 1st is converted at April 1st's rate, not today's.
    4. Sum across all active subs for that app and date.

    This means a yearly $59.99 subscription contributes ~$5/mo to MRR, not \$59.99 — exactly how RevenueCat and ChartMogul model it.
  </Accordion>

  <Accordion title="Churn — paying-subscriber-weighted">
    For each `(app, date)` we compute:

    ```
    churn_rate = canceled_subscriptions[date] / paying_subscribers[date - 1]
    ```

    When you query without `appId`, churn across apps is **weighted by paying subscribers**, not averaged:

    ```
    weighted_churn = Σ (paying_subscribers[app] × churn_rate[app]) / Σ paying_subscribers[app]
    ```

    A 10-user app with 100% churn next to a 10,000-user app with 5% churn produces a weighted churn near 5%, which reflects business reality.
  </Accordion>

  <Accordion title="Trial conversion rate">
    ```
    trial_conversion_rate = Σ trial_conversions / Σ trial_starts   (over the window)
    ```

    Note: a trial that started in March and converted in April will appear as `trial_starts` in March and `trial_conversions` in April. Over a long enough window the ratio converges to the true conversion rate; over a short window it can read above 100% if a backlog of older trials converts (this is normal).
  </Accordion>

  <Accordion title="Event categories">
    We map Apple's free-text event strings to consistent categories:

    | Apple event                                  | Mapped to                   |
    | -------------------------------------------- | --------------------------- |
    | `Subscribe`, `Renew`                         | `new_subscriptions`         |
    | `Cancel`, `Auto-Renew Off`                   | `canceled_subscriptions`    |
    | `Refund`                                     | `refunded_subscriptions`    |
    | `Reactivate`                                 | `reactivated_subscriptions` |
    | `Subscribe with Trial`, `Free Trial Started` | `trial_starts`              |
    | `Convert to Paid Subscription`               | `trial_conversions`         |
    | `Subscription Expired`                       | `expired_subscriptions`     |
    | `Billing Retry`                              | `billing_retries`           |

    Unknown event strings are logged and ignored — they won't break aggregation.
  </Accordion>
</AccordionGroup>

***

## MCP Tool

This endpoint is exposed as an MCP tool so AI assistants can analyze revenue health on your behalf:

| Tool                       | Description                                                |
| -------------------------- | ---------------------------------------------------------- |
| `asc_subscription_metrics` | MRR / ARR / ARPU / churn / trial conversion + daily series |

Example prompt:

```
Show me MRR and churn trend for the last 90 days for app 6759740679,
then explain whether the recent MRR growth is driven by new subscribers
or lower churn.
```

***

## Common Workflows

### Daily revenue dashboard

```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const res = await fetch(
  "https://api.appeeky.com/v1/connect/metrics/subscriptions",
  { headers: { "X-API-Key": process.env.APEEKY_KEY } }
);
const { data } = await res.json();

console.log(`MRR: $${data.totals.mrr_usd}`);
console.log(`Δ MRR: ${(data.totals.mrr_delta_pct * 100).toFixed(1)}%`);
console.log(`Churn: ${(data.totals.avg_churn_rate * 100).toFixed(2)}%`);
console.log(`Trial → Paid: ${(data.totals.trial_conversion_rate * 100).toFixed(1)}%`);

// Render the daily MRR series in your chart of choice
const points = data.series.map((d) => ({ x: d.metric_date, y: d.mrr_usd }));
```

### Identify your highest-churn app

```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
const { data } = await fetch(
  "https://api.appeeky.com/v1/connect/metrics/subscriptions",
  { headers: { "X-API-Key": process.env.APEEKY_KEY } }
).then((r) => r.json());

const worst = data.apps
  .filter((a) => a.paying_subscribers > 50)
  .sort((a, b) => b.churn_rate - a.churn_rate)[0];

console.log(
  `${worst.appName} has ${(worst.churn_rate * 100).toFixed(2)}% monthly churn`
);
```

***

## Error Codes

| Status | Code                  | When                                   |
| ------ | --------------------- | -------------------------------------- |
| 401    | `INVALID_API_KEY`     | Invalid or inactive API key            |
| 403    | `PRO_FEATURE`         | Free plan — upgrade to Indie or higher |
| 404    | `USER_NOT_FOUND`      | User not in system (connect ASC first) |
| 429    | `RATE_LIMIT_EXCEEDED` | Not enough credits                     |
| 500    | `METRICS_ERROR`       | Database or sync error                 |

***

## Limits & Caveats

* Data is computed from Apple's daily reports, which are typically available **1–2 days after the day they cover**. Today's date will usually have no data; yesterday's may be partial.
* MRR uses **developer proceeds** (post-Apple-cut), not list price. This matches what hits your bank account.
* Churn is computed from cancellation **events**, not from comparing subscriber counts day-over-day. This avoids skew from new subscribers added the same day.
* Refunds reduce revenue but are reported separately; they do not subtract from `mrr_usd` directly. For "net MRR after refunds", subtract `refunded_subscriptions × ARPU` from `mrr_usd`.
* Backfill on first connect covers the last **30 days**.
