---
title: "Project a transient aggregate without persisting it"
method: POST
path: "/companies/{companyId}/forecast/projection/preview"
tags: ["Forecast"]
---

# Project a transient aggregate without persisting it

`POST /companies/{companyId}/forecast/projection/preview`

## Request

- Base URL: `https://api.medianfi.com/api/v1`
- URL: `https://api.medianfi.com/api/v1/companies/{companyId}/forecast/projection/preview`
- Auth: HTTP bearer

## Request body

- object
  - `horizon` 12 | 18 | 24
  - `levers` string[]
  - `model` ForecastModel, required
    - `id` string, uuid, required
    - `companyId` string, uuid, required
    - `entityId` string, uuid, required
    - `label` string, required
    - `businessType` 'software' | 'services' | 'digital' | 'usage' | 'license' | 'blended' | 'custom', required
    - `startCashCents` integer, required: Starting cash in the model's authoritative minor units
    - `horizonMonths` 12 | 18 | 24, required
    - `currency` string, required: Server-owned legal-entity functional currency
    - `minorUnitExponent` 2, required: Server-owned scale for every monetary integer in this Forecast model
    - `moneyAuthorityVersion` 1, required
    - `source` 'unknown' | 'manual' | 'books', required: Provenance of the model's opening cash boundary
    - `sourceMetadata` object, required: Non-secret authority metadata such as closed period, anchor, and functional currency
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `streams` ForecastStream[]
    - `id` string, uuid
    - `forecastId` string, uuid
    - `type` 'subscription' | 'usage' | 'license' | 'onetime' | 'services_hours' | 'services_retainer' | 'ledger_run_rate'
    - `label` string
    - `position` integer
    - `drivers` object
    - `archived` boolean
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
  - `headcount` ForecastHeadcount[]
    - `id` string, uuid
    - `forecastId` string, uuid
    - `role` string
    - `employmentType` 'w2' | 'contractor'
    - `count` integer
    - `monthlyCostCents` integer: Monthly cost per head in the model's authoritative minor units
    - `startOffset` integer
    - `rampMonths` integer
    - `position` integer
  - `opex` ForecastOpex[]
    - `id` string, uuid
    - `forecastId` string, uuid
    - `name` string
    - `behavior` 'fixed' | 'pct_revenue' | 'per_head'
    - `amountCents` integer, nullable: Fixed or per-head amount in the model's authoritative minor units
    - `pct` number, nullable: Percentage of revenue (for pct_revenue), in [0,1]
    - `position` integer
  - `scenarios` ForecastScenario[]
    - `id` string, uuid
    - `forecastId` string, uuid
    - `name` string
    - `kind` 'adhoc' | 'budget'
    - `isLocked` boolean
    - `baseModelId` string, uuid, nullable
    - `overrides` object
    - `createdAt` string, date-time

## Response `200`

Projection result (not persisted)

- object
  - `success` boolean
  - `data` ProjectionResult: Full projection result with all three scenarios, runway, and KPIs
    - `scenarios` object, required
      - `worst` MonthlyPoint[], required
        - `offset` integer, required: 0-based month offset from model start
        - `label` string, required: Human-readable month label (e.g. "Jul 26")
        - `revenueCents` integer, required: Total revenue in the response's authoritative minor units
        - `byStreamCents` object, required: Revenue by stream ID in the response's authoritative minor units
        - `peopleCents` integer, required: Headcount cost in the response's authoritative minor units
        - `opexCents` integer, required: Operating expense in the response's authoritative minor units
        - `financingCents` integer, required: Timed non-revenue capital cash flow in the response's authoritative minor units
        - `netCents` integer, required: Net income excluding financing, in the response's authoritative minor units
        - `endingCents` integer, required: Ending cash balance in the response's authoritative minor units
        - `cashMovementCents` integer: Projected rows only (#2652). Cash this row adds to the prior ending cash — operating net (for offset 0, prorated to the days of the current month after cashAsOfDate, half a minor unit rounding away from zero) plus financing — so prior ending + cashMovementCents = endingCents.
        - `marginPct` number, required: Net margin (0 when revenue is 0)
      - `base` MonthlyPoint[], required
        - `offset` integer, required: 0-based month offset from model start
        - `label` string, required: Human-readable month label (e.g. "Jul 26")
        - `revenueCents` integer, required: Total revenue in the response's authoritative minor units
        - `byStreamCents` object, required: Revenue by stream ID in the response's authoritative minor units
        - `peopleCents` integer, required: Headcount cost in the response's authoritative minor units
        - `opexCents` integer, required: Operating expense in the response's authoritative minor units
        - `financingCents` integer, required: Timed non-revenue capital cash flow in the response's authoritative minor units
        - `netCents` integer, required: Net income excluding financing, in the response's authoritative minor units
        - `endingCents` integer, required: Ending cash balance in the response's authoritative minor units
        - `cashMovementCents` integer: Projected rows only (#2652). Cash this row adds to the prior ending cash — operating net (for offset 0, prorated to the days of the current month after cashAsOfDate, half a minor unit rounding away from zero) plus financing — so prior ending + cashMovementCents = endingCents.
        - `marginPct` number, required: Net margin (0 when revenue is 0)
      - `best` MonthlyPoint[], required
        - `offset` integer, required: 0-based month offset from model start
        - `label` string, required: Human-readable month label (e.g. "Jul 26")
        - `revenueCents` integer, required: Total revenue in the response's authoritative minor units
        - `byStreamCents` object, required: Revenue by stream ID in the response's authoritative minor units
        - `peopleCents` integer, required: Headcount cost in the response's authoritative minor units
        - `opexCents` integer, required: Operating expense in the response's authoritative minor units
        - `financingCents` integer, required: Timed non-revenue capital cash flow in the response's authoritative minor units
        - `netCents` integer, required: Net income excluding financing, in the response's authoritative minor units
        - `endingCents` integer, required: Ending cash balance in the response's authoritative minor units
        - `cashMovementCents` integer: Projected rows only (#2652). Cash this row adds to the prior ending cash — operating net (for offset 0, prorated to the days of the current month after cashAsOfDate, half a minor unit rounding away from zero) plus financing — so prior ending + cashMovementCents = endingCents.
        - `marginPct` number, required: Net margin (0 when revenue is 0)
    - `actuals` MonthlyPoint[], required: Historical actuals (empty until
      - `offset` integer, required: 0-based month offset from model start
      - `label` string, required: Human-readable month label (e.g. "Jul 26")
      - `revenueCents` integer, required: Total revenue in the response's authoritative minor units
      - `byStreamCents` object, required: Revenue by stream ID in the response's authoritative minor units
      - `peopleCents` integer, required: Headcount cost in the response's authoritative minor units
      - `opexCents` integer, required: Operating expense in the response's authoritative minor units
      - `financingCents` integer, required: Timed non-revenue capital cash flow in the response's authoritative minor units
      - `netCents` integer, required: Net income excluding financing, in the response's authoritative minor units
      - `endingCents` integer, required: Ending cash balance in the response's authoritative minor units
      - `cashMovementCents` integer: Projected rows only (#2652). Cash this row adds to the prior ending cash — operating net (for offset 0, prorated to the days of the current month after cashAsOfDate, half a minor unit rounding away from zero) plus financing — so prior ending + cashMovementCents = endingCents.
      - `marginPct` number, required: Net margin (0 when revenue is 0)
    - `functionalCurrency` string, required: Functional currency of the authoritative ledger cash boundary
    - `minorUnitExponent` 2, required
    - `moneyAuthorityVersion` 1, required
    - `anchorYyyyMm` string, nullable, required: First projected month; the current UTC calendar month (actuals run through the month before it)
    - `cashAsOfYyyyMm` string, nullable, required: Calendar month whose posted books cash anchors the forecast (null when the persisted model's cash is used)
    - `cashAsOfDate` string, date, nullable: Date the posted books start cash is stated at (#2652; today for live reads, the month end for close snapshots; null when the persisted model's cash is used)
    - `cashAsOfAt` string, date-time, nullable: Instant the live books cash was read (UTC ISO timestamp), so clients can state the as-of date in the viewer's time zone; null for close snapshots and persisted model cash. Proration uses cashAsOfDate, not this field.
    - `runway` object, required
      - `months` integer, nullable: Months of runway remaining (null when no shortfall is projected)
      - `profitable` boolean, required: True when cash never declines over the horizon
    - `recurringMixPct` number, nullable, required: Fraction of current-month base revenue that is recurring; null when source data cannot prove recurrence
    - `horizonSummaries` object: Summaries keyed by visible month count for 6, 12 and the full projection length when available. Select these with the corresponding scenario prefix; never extrapolate runway in the client. Legacy payloads may omit this object and support only their full horizon.
    - `kpis` object, required
      - `cashOnHandCents` integer, required: Current cash on hand in the supplied currency's minor units
      - `nextMonthNetCents` integer, required: Projected net income for the calendar month after the current month (offset 1; offset 0 is the current, partly elapsed month) in the supplied currency's minor units

## Other responses

- `401`: Authentication required
- `403`: Insufficient permissions or not a company member
- `404`: Resource not found
- `422`: Validation error

---

[API](https://skmtc.dev/medianfi/apis/median-api.md) · [All operations](https://skmtc.dev/medianfi/apis/median-api/llms.txt) · [OpenAPI document](https://skmtc.dev/medianfi/apis/median-api/revisions/20090ea32b0d?raw)
