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

# Analytics · Cost

> Cost sliced by agent, customer, signal, day, plan, and model, with optional period-over-period trend

# Cost analytics

`GET /v1/analytics/cost` is the single place to read cost out of MarginFront with a full breakdown attached. Use it when you need to answer:

* Which agents cost the most to run?
* Which customers are driving the cost?
* What is our cost trend day over day?
* How did this window compare to the window before it?

Cost is tracked independently of pricing and subscriptions. An event contributes cost as long as it has a recorded `usageCost`, whether or not the customer has a paid plan. Useful for Cost-Tracking-mode organizations that are not billing yet.

This is a read-only endpoint.

***

## The endpoint

**Method and URL:**

```
GET /v1/analytics/cost
```

Auth: API key in the `x-api-key` header.

***

## Query parameters

| Param                | Type     | Required | Description                                                                                     |
| -------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------- |
| `startDate`          | ISO date | yes      | Start of the window (inclusive). Example: `2026-04-01`.                                         |
| `endDate`            | ISO date | yes      | End of the window (inclusive).                                                                  |
| `customerId`         | UUID     | no       | Narrow to one customer.                                                                         |
| `subscriptionId`     | UUID     | no       | Narrow to one subscription.                                                                     |
| `agentId`            | UUID     | no       | Narrow to one agent.                                                                            |
| `signalId`           | UUID     | no       | Narrow to one signal.                                                                           |
| `includePriorWindow` | boolean  | no       | When `true`, the response also includes a `prior` field with the same shape for the prior span. |

### How the prior window works

If you pass `includePriorWindow=true`, the API computes a second window of the same length immediately before your primary window, and runs the same aggregation on it. You get both shapes back in one call. That is how you build period-over-period trend widgets without a second round-trip.

One extra database query is used when this flag is set. Omit it when you do not need the trend.

***

## Example curl calls

**Org-wide cost for April 2026:**

```bash theme={null}
curl "https://api.marginfront.com/v1/analytics/cost?startDate=2026-04-01&endDate=2026-04-30" \
  -H "x-api-key: mf_sk_test_..."
```

**One customer's cost with trend:**

```bash theme={null}
curl "https://api.marginfront.com/v1/analytics/cost?customerId=bc8eceda-50e4-4138-b2a2-47e92d344540&startDate=2026-04-01&endDate=2026-04-30&includePriorWindow=true" \
  -H "x-api-key: mf_sk_test_..."
```

**One agent's cost broken down by day (the response always includes `byDay`):**

```bash theme={null}
curl "https://api.marginfront.com/v1/analytics/cost?agentId=3a1948ea-a701-4752-8c3d-df6c2f5833cf&startDate=2026-04-01&endDate=2026-04-30" \
  -H "x-api-key: mf_sk_test_..."
```

***

## What you get back (`200 OK`)

```json theme={null}
{
  "cost": 3122.18,
  "eventCount": 41233,
  "eventCountWithNullCost": 12,

  "byAgent": [
    {
      "agentId": "b47e12fa-...",
      "cost": 1982.4,
      "eventCount": 24102
    }
  ],

  "byCustomer": [
    {
      "customerId": "5e7f8a3d-...",
      "cost": 742.8,
      "eventCount": 9801
    }
  ],

  "bySignal": [
    {
      "signalId": "69145379-...",
      "cost": 2104.5,
      "eventCount": 28940
    }
  ],

  "byDay": [
    {
      "date": "2026-04-01T00:00:00.000Z",
      "cost": 94.82,
      "eventCount": 1243
    },
    {
      "date": "2026-04-02T00:00:00.000Z",
      "cost": 102.15,
      "eventCount": 1378
    }
  ],

  "byPlan": [
    {
      "planId": "a1b2c3d4-...",
      "cost": 2843.1,
      "eventCount": 37120
    },
    {
      "planId": null,
      "cost": 279.08,
      "eventCount": 4113
    }
  ],

  "byModel": [
    {
      "model": "gpt-4o-mini",
      "cost": 1820.4,
      "eventCount": 22014
    },
    {
      "model": "claude-3-5-sonnet",
      "cost": 1301.78,
      "eventCount": 19219
    },
    {
      "model": null,
      "cost": 0.0,
      "eventCount": 0
    }
  ]
}
```

When `includePriorWindow=true` is set, a `prior` field appears at the top level with the same shape (minus its own `prior`):

```json theme={null}
{
  "cost": 3122.18,
  "eventCount": 41233,
  "eventCountWithNullCost": 12,
  "byAgent": [],
  "byCustomer": [],
  "bySignal": [],
  "byDay": [],
  "byPlan": [],
  "byModel": [],
  "prior": {
    "cost": 2847.62,
    "eventCount": 38015,
    "eventCountWithNullCost": 4,
    "byAgent": [],
    "byCustomer": [],
    "bySignal": [],
    "byDay": [],
    "byPlan": [],
    "byModel": []
  }
}
```

### Understanding the response

* **`cost`** is the total cost for the window: the sum of `usageCost` across every event that fell inside.
* **`eventCount`** counts every event in the window, including events whose `usageCost` is blank.
* **`eventCountWithNullCost`** is the subset whose cost could not be computed. They are in `eventCount` but contribute `0` to `cost`. Treat this as a "needs attention" indicator.
* **`byAgent` / `byCustomer` / `bySignal` / `byPlan`** are one row per entity, with cost and event count for that entity in the window.
* **`bySignal`** can include a row where `signalId` is `null`. Those are events whose signal could not be attributed.
* **`byPlan`** can include a row where `planId` is `null`. Those are orphan events: events with no subscription, or whose subscription was deleted. They still contribute to cost.
* **`byDay`** is one row per UTC day that had activity. `date` is UTC midnight. Use this to chart daily trends.
* **`byModel`** is one row per LLM model name, pulled from the event's payload. `model: null` covers non-LLM events and LLM events where the model field was missing.
* **`prior`** appears only when you pass `includePriorWindow=true`. Same shape as the primary window, same length of time, immediately before the primary window.

All money fields are `number`, not strings.

***

## When to use this vs. other endpoints

Use **this endpoint** when you want cost broken down by something: which agent, which customer, which signal, which day, which plan, which model.

Use [`/v1/analytics/revenue`](./analytics-revenue) when you also need revenue, margin, and pricing-strategy attribution.

Use [`/v1/analytics/usage`](./analytics) when you want event counts and quantity totals without pricing math.

***

## Using the Node SDK

```typescript theme={null}
import { MarginFrontClient } from "@marginfront/sdk";

const mf = new MarginFrontClient(process.env.MF_API_SECRET_KEY);

const cost = await mf.analytics.costBreakdown({
  startDate: "2026-04-01",
  endDate: "2026-04-30",
  includePriorWindow: true,
});

console.log(`Cost this month: $${cost.cost.toFixed(2)}`);

if (cost.prior) {
  const delta = cost.cost - cost.prior.cost;
  console.log(`Change vs prior window: $${delta.toFixed(2)}`);
}
```

See the [SDK analytics page](/sdk/analytics) for all seven analytics methods.

***

## Common errors

* **`400 Bad Request`**: `startDate` or `endDate` is missing, in the wrong format, or a UUID filter is invalid.
* **`401 Unauthorized`**: API key missing or wrong.
