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

# Drill-downs

> Die Zeilen hinter jeder Zelle der Finanzberichte abrufen: Kennzahlen, Pflichtparameter, Seiten und wie die Summe der Zeilen den Wert der Zelle ergibt.

Jede Zahl der Finanzberichte lässt sich bis zu den Positionen, Rechnungen und Zahlungen zurückverfolgen, aus denen sie besteht. Das erledigt ein einziger Endpunkt: `GET /api/analytics/mrr-financials/details`. Du nennst die Kennzahl (`metric`) und den Monat, die API liefert die Zeilen seitenweise und ihre Summe über alle Seiten.

## Ein Beispiel

Im September 2026 hat die Taktwerk GmbH 1.338,00 € MRR verloren. Die Zeilen dahinter:

```bash theme={null}
curl "https://coreapi.io/api/analytics/mrr-financials/details?metric=lost&month=2026-09&scope=customer" \
  -H "Authorization: Bearer api_DEIN_TOKEN"
```

```json theme={null}
{
  "data": [
    {
      "kind": "movement",
      "id": "0199c0de-0000-7000-8000-d00000052001",
      "month": "2026-09",
      "amount": {
        "amount": "-1189.00",
        "currency": "EUR"
      },
      "account": {
        "key": "0199c0de-0000-7000-8000-c00000000052",
        "label": "Steirerhof Catering GmbH"
      },
      "customer": {
        "id": "0199c0de-0000-7000-8000-c00000000052",
        "number": "K-10052",
        "name": "Steirerhof Catering GmbH"
      },
      "subscription": {
        "id": "0199c0de-0000-7000-8000-b00000000052",
        "number": "ABO-2052",
        "name": "ABO-2052"
      },
      "item": {
        "id": "0199c0de-0000-7000-8000-d00000052001",
        "name": "Plattform",
        "productName": "Plattform"
      },
      "product": {
        "id": "0199c0de-0000-7000-8000-00000000f001",
        "number": null,
        "name": "Plattform"
      },
      "movementType": "lost",
      "reason": "contract_end",
      "reasons": {
        "contract_end": {
          "amount": "-1189.00",
          "currency": "EUR"
        }
      },
      "mrrBop": {
        "amount": "1189.00",
        "currency": "EUR"
      },
      "mrrEop": {
        "amount": "0.00",
        "currency": "EUR"
      },
      "delta": {
        "amount": "-1189.00",
        "currency": "EUR"
      },
      "cancellationReason": "closed"
    },
    {
      "kind": "movement",
      "id": "0199c0de-0000-7000-8000-d00000052002",
      "month": "2026-09",
      "amount": {
        "amount": "-149.00",
        "currency": "EUR"
      },
      "account": {
        "key": "0199c0de-0000-7000-8000-c00000000052",
        "label": "Steirerhof Catering GmbH"
      },
      "customer": {
        "id": "0199c0de-0000-7000-8000-c00000000052",
        "number": "K-10052",
        "name": "Steirerhof Catering GmbH"
      },
      "subscription": {
        "id": "0199c0de-0000-7000-8000-b00000000052",
        "number": "ABO-2052",
        "name": "ABO-2052"
      },
      "item": {
        "id": "0199c0de-0000-7000-8000-d00000052002",
        "name": "Schichtplanung",
        "productName": "Schichtplanung"
      },
      "product": {
        "id": "0199c0de-0000-7000-8000-00000000f002",
        "number": null,
        "name": "Schichtplanung"
      },
      "movementType": "lost",
      "reason": "contract_end",
      "reasons": {
        "contract_end": {
          "amount": "-149.00",
          "currency": "EUR"
        }
      },
      "mrrBop": {
        "amount": "149.00",
        "currency": "EUR"
      },
      "mrrEop": {
        "amount": "0.00",
        "currency": "EUR"
      },
      "delta": {
        "amount": "-149.00",
        "currency": "EUR"
      },
      "cancellationReason": "closed"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 25,
    "total": 2,
    "sum": {
      "amount": "-1338.00",
      "currency": "EUR"
    },
    "asOf": "2026-10-01T04:00:00+00:00"
  }
}
```

Das eine verlorene Konto ist die Steirerhof Catering GmbH mit zwei Positionen: Plattform über 1.189,00 € und Schichtplanung über 149,00 €, Kündigungsgrund `closed`. `meta.sum` ist −1.338,00 €, der negative Wert der Zelle `rows.lost` im September. Die Zelle zeigt den Verlust als positiven Betrag, die Zeilen tragen die Änderung mit Vorzeichen. Für alle anderen Kennzahlen ist `meta.sum` gleich dem Wert der Zelle.

## Parameter

Der Drill-down übernimmt die Filter der Seite: `currency`, `scope`, `segmentId`, `customerIds[]`, `productIds[]`. Schick dieselben Werte mit wie beim Datensatz, sonst passen Zeilen und Zelle nicht zusammen.

| Parameter | Bedeutung |
| - | - |
| `metric` | die Kennzahl der Zelle, Pflicht |
| `month` | Monat der Zelle, Pflicht außer bei Forderungsalter, Umsatzseite, `cohort` und `churn_reason` |
| `from`, `to` | Zeitraum statt Monat für die Umsatzseite und `churn_reason` |
| `reason` | nur diese Ursachen, kommagetrennt (`discount_start,discount_end,discount_change`); bei `billing_gap` die Ursache |
| `search` | Freitext über Kundenname und -nummer, Abonnement, Position, Produkt und Rechnungsnummer |
| `groupBy=document` | Umsatzzeilen je Rechnung gruppiert, mit den zugehörigen Stornos und Gutschriften |
| `part` | nur bei `cash_correction`: `reversed` liefert die stornierten Buchungen (positiv), `counter` die Gegenbuchungen (negativ), ohne `part` beide Seiten |
| `page`, `pageSize` | Seite ab 1, 25 Zeilen je Seite, höchstens 200 |

## Kennzahlen

Das Feld `kind` jeder Zeile sagt, welche Felder gesetzt sind. Die Tabelle nennt für jede der 57 Kennzahlen die Art der Zeilen und die zusätzlichen Parameter.

| `metric` | Zeilen (`kind`) | Zusätzliche Parameter |
| - | - | - |
| `new`, `expansion`, `contraction`, `lost`, `resurrecting` | `movement`: die Positionen der Konten mit dieser Bewegung | `reason`; bei `lost` mit `reason=contract_end` auch `cancellationReason` |
| `mrr_bop`, `mrr_eop` | `snapshot`: die Positionen mit MRR am Monatsende, mit Stückpreis, Menge und Intervall | |
| `one_off`, `variable` | `revenue`: Rechnungspositionen, netto | `groupBy=document` |
| `cash_collected`, `cash_collected_refund_returned`, `cash_refunded`, `cash_refunded_refund`, `cash_refunded_chargeback`, `cash_refunded_payout`, `cash_refunded_return_fee`, `cash_net` | `cash`: Zahlungseingänge und Zahlungsausgänge nach Zahldatum; die Teile gefiltert auf zurückgekommene Erstattungen, Erstattungen, Rücklastschriften und Chargebacks, Auszahlungen oder Rücklastschrift-Gebühren | |
| `cash_correction` | `cash`: von Hand stornierte Zahlungen und Erstattungen mit ihrer Gegenbuchung (`counterpartTransactionId`); jede Zeile mit Vorzeichen, zusammen 0 | `part` (`reversed` oder `counter`) für eine Seite, wie in den Zeilen „Storniert“ und „Gegenbuchung“ |
| `cash_collected_this_month`, `cash_collected_other_months`, `cash_collected_unassigned` | `cash`: der Teil der Zahlung, der auf Rechnungen des Monats, anderer Monate oder auf keine Rechnung entfällt | |
| `cash_in`, `cash_out` | `cash`: Zeilen der Forderungstabelle | |
| `billed_gross`, `billed_net`, `status_paid`, `status_settled`, `status_open`, `status_overdue`, `status_credited`, `status_written_off`, `status_overpaid`, `cash_in_for_month` | `invoice`: die im Monat abgeschlossenen Rechnungen mit dem Betrag dieser Zeile | |
| `receivables_eop`, `outstanding_eop`, `outstanding_not_due_eop`, `outstanding_overdue_eop` | `invoice`: die am Monatsende offenen Rechnungen | |
| `owed_to_customers` | `invoice`: Rechnungen, bei denen Kunden mehr bezahlt haben, als noch gefordert ist | |
| `forecast_invoice` | `forecast`: erwartete Rechnungen der Abrechnungsprognose, brutto, mit Abrechnungszeitraum | |
| `accounted_mrr` | `accounted`: wiederkehrende Rechnungspositionen mit ihrem Anteil am Monat | |
| `billing_gap` | `billing_gap`: je Position und Ursache die Differenz Vertrag zu Rechnung | `reason` |
| `ageing_not_due`, `ageing_1_30`, `ageing_31_60`, `ageing_61_90`, `ageing_over_90` | `invoice`: die heute offenen Rechnungen des Buckets | kein `month` |
| `revenue_product` | `revenue` | `productId`, `month` oder `from`/`to`, `groupBy=document` |
| `revenue_customer_product` | `revenue` | `customerId`, `productId`, `month` oder `from`/`to`, `groupBy=document` |
| `revenue_country` | `revenue` | `countryCode` (`none` für Positionen ohne Land), `month` oder `from`/`to`, `groupBy=document` |
| `cohort` | `snapshot`: die Positionen der Kohortenkonten | `cohortMonth` und `age`, kein `month` |
| `churn_reason` | `movement`: die Positionen der verlorenen Konten | `cancellationReason` (ein Code, `none`, `pause` oder `voided`), `month` oder `from`/`to` |
| `backlog_event` | `forward`: bekannte künftige Änderungen des Monats | `eventKind`, `customerId`, `productId` |
| `payment_behaviour` | `invoice`: im Monat bezahlte Rechnungen mit `daysToPayment` | `paymentMethod` |
| `logo_new`, `logo_lost` | `movement`: die Positionen der neuen oder verlorenen Konten | |
| `restatement` | Hinweise mit Erklärung statt Zeilen, siehe unten | `cell` |
| `build_failure` | `build_failure`: die Abweichungen der zuletzt abgebrochenen Berechnung | kein `month`, `search` |

## Was eine Zeile bedeutet

`amount` ist immer der Anteil der Zeile an der Zelle. Die anderen Felder erklären, wie er zustande kommt.

**Accounted MRR.** Die Rechnung RE-2026-0206 der Hafenkontor Spedition GmbH hat einen Leistungszeitraum vom 01.06. bis ausschließlich 01.07.2026. Alle 30 Tage liegen im Juni, der Anteil am Monat ist der volle Nettobetrag von 4.303,00 €:

```json theme={null}
{
  "kind": "accounted",
  "id": "0199c0de-0000-7000-8000-e00000020601",
  "month": "2026-06",
  "amount": {
    "amount": "4303.00",
    "currency": "EUR"
  },
  "customer": {
    "id": "0199c0de-0000-7000-8000-c00000000003",
    "number": "K-10003",
    "name": "Hafenkontor Spedition GmbH"
  },
  "product": {
    "id": "0199c0de-0000-7000-8000-00000000f001",
    "number": null,
    "name": "Plattform"
  },
  "invoice": {
    "id": "0199c0de-0000-7000-8000-000000000506",
    "number": "RE-2026-0206",
    "type": "TYPE_INVOICE",
    "status": "STATUS_PAID"
  },
  "positionName": "Plattform und Lohnexport, Juni 2026",
  "netAmount": {
    "amount": "4303.00",
    "currency": "EUR"
  },
  "from": "2026-06-01T00:00:00+02:00",
  "to": "2026-07-01T00:00:00+02:00",
  "days": 30,
  "totalDays": 30
}
```

Längere Leistungszeiträume teilt die Berechnung nach 30/360, damit jeder volle Monat gleich viel beiträgt. Eine Jahresrechnung über 1.200,00 € für das Kalenderjahr trägt in jedem Monat 30 von 360 Tagen bei, also 100,00 €. Die Beträge der Zeilen werden mit sechs Nachkommastellen gerechnet und erst in der Zelle gerundet. So ergibt die Summe der Zeilen die Zelle auch bei Beträgen wie 2.980,00 € / 12.

**Differenz Vertrag zu Rechnung.** Eine `billing_gap`-Zeile vergleicht je Position den Vertrag (`contractAmount`), den erwarteten Rechnungsbetrag nach Vertragstagen im Monat (`expectedAmount`) und den Accounted MRR (`accountedAmount`). `amount` ist der Teil der Differenz, den die Ursache `cause` erklärt, gerechnet als Vertrag minus Rechnung:

```json theme={null}
{
  "kind": "billing_gap",
  "id": "0199c0de-0000-7000-8000-d00000018003",
  "month": "2026-08",
  "amount": {
    "amount": "79.00",
    "currency": "EUR"
  },
  "customer": {
    "id": "0199c0de-0000-7000-8000-c00000000018",
    "number": "K-10018",
    "name": "Havelland Reinigung GmbH"
  },
  "subscription": {
    "id": "0199c0de-0000-7000-8000-b00000000018",
    "number": "ABO-2018",
    "name": "ABO-2018"
  },
  "item": {
    "id": "0199c0de-0000-7000-8000-d00000018003",
    "name": "Lohnexport",
    "productName": "Lohnexport"
  },
  "contractAmount": {
    "amount": "79.00",
    "currency": "EUR"
  },
  "expectedAmount": {
    "amount": "79.00",
    "currency": "EUR"
  },
  "accountedAmount": {
    "amount": "0.00",
    "currency": "EUR"
  },
  "cause": "not_yet_billed",
  "causeLabel": "Rechnung ausstehend",
  "expectedText": null
}
```

Das Produkt Lohnexport der Havelland Reinigung GmbH hat im August 79,00 € im Vertrag, eine Rechnung für August gibt es noch nicht. Die Summe 79,00 € entspricht der Zelle `billing_gap` im August. Mit `reason=not_yet_billed` erhältst du nur die Zeilen einer Ursache.

Für vergangene Monate ohne Rechnung unterscheidet die Berechnung zwei Ursachen. `not_yet_billed` (Rechnung ausstehend) heißt: Der nächste Abrechnungslauf rechnet den Monat ab, weil noch eine Abrechnungsposition offen ist oder das nächste Abrechnungsdatum vor dem Monatsende liegt. `not_billed` (Nicht abgerechnet) heißt: Kein Lauf wird den Monat abrechnen. Dazu entsteht je Position ein Hinweis `NOT_BILLED` mit den Monaten und dem Betrag. `upcoming_invoice` (Rechnung folgt) gilt nur für den laufenden und spätere Monate.

**Rechnungsprognose.** Eine `forecast`-Zeile nennt die erwartete Rechnung mit Rechnungsdatum (`invoiceDate`), dem Bruttobetrag in `amount` und in `from` und `to` den Abrechnungszeitraum:

```json theme={null}
{
  "kind": "forecast",
  "id": "0199c0de-0000-7000-8000-f00000031003",
  "month": "2026-10",
  "amount": {
    "amount": "5120.57",
    "currency": "EUR"
  },
  "customer": {
    "id": "0199c0de-0000-7000-8000-c00000000003",
    "number": "K-10003",
    "name": "Hafenkontor Spedition GmbH"
  },
  "subscription": {
    "id": "0199c0de-0000-7000-8000-b00000000003",
    "number": "ABO-2003",
    "name": "ABO-2003"
  },
  "invoiceDate": "2026-10-01T00:00:00+02:00",
  "from": "2026-10-01T00:00:00+02:00",
  "to": "2026-11-01T00:00:00+01:00",
  "billableSince": null,
  "forecastKind": "pending_billing_item"
}
```

`forecastKind` sagt, woher die Zeile kommt: `pending_billing_item` (alle Abrechnungspositionen der Rechnung sind schon angelegt), `projected` (aus der Abrechnungsprognose hochgerechnet) oder `pending_credit` (eine offene Gutschrift, die einzige negative Prognosezeile). Holt der nächste Lauf vergangene Zeiträume nach, fasst die Prognose sie wie der Lauf zu einer Rechnung am heutigen Tag zusammen, und `billableSince` nennt den Tag, seit dem sie abrechenbar ist. Doppelte Rechnungen der Abrechnungsprognose zählen einmal und erzeugen den Hinweis `FORECAST_DUPLICATE`.

**Zahlungen.** Jede Zahlungszeile nennt in `invoiceMonth` den Abschlussmonat der Rechnung, die sie bezahlt. Wird eine Rechnung überzahlt, teilt sich die Zahlung: Der Teil bis zum Bruttobetrag gehört zur Rechnung, der Rest zu `cash_collected_unassigned`.

**Korrekturen.** Eine Korrektur besteht aus zwei Buchungen, die sich aufheben: der stornierten Buchung und ihrer Gegenbuchung. Ohne `part` liefert `cash_correction` beide, die Summe ist 0. Mit `part=reversed` erhältst du nur die stornierten Buchungen, mit `part=counter` nur die Gegenbuchungen. `meta.sum` ist dann der Wert der Zeile „Storniert“ oder „Gegenbuchung“:

```bash theme={null}
curl "https://coreapi.io/api/analytics/mrr-financials/details?metric=cash_correction&part=reversed&month=2026-04&scope=customer" \
  -H "Authorization: Bearer api_DEIN_TOKEN"
```

```json theme={null}
{
  "data": [
    {
      "kind": "cash",
      "id": "0199c0de-0000-7000-8000-a00000041001",
      "month": "2026-04",
      "amount": {
        "amount": "119.00",
        "currency": "EUR"
      },
      "customer": {
        "id": "0199c0de-0000-7000-8000-c00000000041",
        "number": "K-10041",
        "name": "Ostseewind Yachtservice GmbH"
      },
      "invoice": {
        "id": "0199c0de-0000-7000-8000-000000000741",
        "number": "GS-2026-0041",
        "type": "TYPE_CREDIT",
        "status": "STATUS_REFUNDED"
      },
      "transaction": {
        "id": "0199c0de-0000-7000-8000-a00000041001",
        "type": "correction"
      },
      "reason": "correction",
      "paidDate": "2026-04-21T10:00:00+02:00",
      "invoiceMonth": "2026-03",
      "counterpartTransactionId": "0199c0de-0000-7000-8000-a00000041002"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 25,
    "total": 1,
    "sum": {
      "amount": "119.00",
      "currency": "EUR"
    },
    "asOf": "2026-05-01T04:00:00+00:00"
  }
}
```

Die Buchung über 119,00 € vom 21.04.2026 auf die Gutschrift GS-2026-0041 wurde am 28.04.2026 mit −119,00 € gegengebucht. `counterpartTransactionId` nennt diese Gegenbuchung, `part=counter` liefert sie mit −119,00 €. `part` gibt es nur für `cash_correction`. Bei jeder anderen Kennzahl antwortet die API mit 422, siehe [Fehler](https://docs.fynn.eu/v2-finance-api/errors.md).

**Belegsicht.** Mit `groupBy=document` fasst die API Umsatzzeilen je ursprünglicher Rechnung zusammen, einschließlich der Stornos und Gutschriften, die sich auf sie beziehen. `groupNet` ist Rechnung minus Stornos minus Gutschriften innerhalb der Zelle. Die Seiten zählen dann Gruppen statt Zeilen.

## Abgebrochene Berechnung

`metric=build_failure` braucht keinen Monat und listet die Abweichungen der zuletzt abgebrochenen Berechnung, höchstens 200. Die Liste ist durchsuchbar (`search`) und blätterbar wie jede andere. Die Zeilen haben keinen Betrag, `meta.sum` ist `null`.

```json theme={null}
{
  "kind": "build_failure",
  "check": "CASH_WITHIN_DOCUMENT",
  "invoice": { "id": "0199c0de-0000-7000-8000-0000000a0001", "number": "RE-2026-0314", "label": "RE-2026-0314" },
  "month": "2026-08",
  "expectedText": "collected − overpaid <= gross 23800 + refunded or charged back 0",
  "actualText": "collected 47600 − overpaid 0",
  "sources": []
}
```

`check` nennt die Prüfung, `expectedText` und `actualText` beschreiben, was sie erwartet und was sie gefunden hat. Die Texte sind Diagnosen der Berechnung auf Englisch und nicht zur Anzeige für Endkunden gedacht. Der Endpunkt braucht `analytics:read`.

## Nachträge einer Zelle

`metric=restatement` liefert keine Zeilen, sondern die Nachtrags-Hinweise eines abgeschlossenen Monats mit ihrer Erklärung: Snapshot-Wert, aktueller Wert, Differenz und Ursache. Mit `cell` grenzt du auf eine Zahl ein, zum Beispiel `cell=mrr_eop` oder `cell=reasons.lost.contract_end`. Wie Nachträge entstehen, erklärt [Snapshots](https://docs.fynn.eu/v2-finance-api/snapshots.md).

## Seiten

`meta.total` ist die Zahl aller Zeilen, `meta.sum` ihre Summe über alle Seiten. Für eine Zelle mit 1.200 Zeilen und `pageSize=200` rufst du die Seiten 1 bis 6 ab. Die Reihenfolge ist stabil, solange keine neue Berechnung stattfindet. Prüfe dazu `meta.asOf`: Ändert es sich zwischen zwei Seiten, beginnst du von vorn.

Für große Mengen ohne Seiten nutze die Excel-Bücher: Ihre Rohdaten-Blätter enthalten dieselben Zeilen für den ganzen Zeitraum, siehe [Excel-Exporte](https://docs.fynn.eu/v2-finance-api/excel.md).
