> ## 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.

# SDK vs REST Migration

> Old URL shapes mapped to the new unified API

# The MarginFront API (one surface, unified)

> **Heads up:** this doc used to describe two parallel API surfaces (the SDK API and the admin REST API) and tell you which to pick. Those two surfaces have been **unified**. There is now **one public API** under `/v1/<resource>`. Every endpoint, including the seven endpoints that used to be dashboard-only, now runs through the same canonical library. This doc is kept around as a migration reference for anyone who was using the old routes.

***

## The unified API (what to use today)

All public endpoints live under `/v1/<resource>`:

```
/v1/verify
/v1/customers        /v1/customers/:id        /v1/customers/:id/revenue
/v1/agents           /v1/agents/:id
/v1/signals          /v1/signals/:id
/v1/pricing-plans    /v1/pricing-plans/:id
/v1/subscriptions    /v1/subscriptions/:id    /v1/subscriptions/:id/revenue
/v1/usage/record
/v1/analytics/usage
/v1/analytics/revenue
/v1/analytics/cost
/v1/analytics/mrr
/v1/invoices         /v1/invoices/:id         /v1/invoices/generate         /v1/invoices/:id/send
/v1/portal-sessions  /v1/portal-sessions/:id
```

**Canonical analytics endpoints** (new): [`/v1/analytics/revenue`](./analytics-revenue), [`/v1/analytics/cost`](./analytics-cost), and [`/v1/analytics/mrr`](./analytics-mrr). These three return the same canonical revenue, cost, and MRR shapes the dashboard uses. Per-entity revenue is available at [`/v1/customers/:id/revenue`](./customers#read-a-customer-with-revenue) and [`/v1/subscriptions/:id/revenue`](./subscriptions#read-a-subscription-with-revenue).

**Key points:**

* **No `org/:orgId/` in the URL.** The API key alone identifies your organization. You never need to pass an org ID in a URL anywhere.
* **No `/sdk/` prefix either.** What used to be "SDK-only" endpoints now live at the same top level as everything else.
* **One credential per request.** Pass your API key via the `x-api-key` header. See [authentication.md](./authentication) for the full details.
* **Every endpoint is the same shape whether you call it from curl, the Node SDK, a Python backend, or anything else.** The SDK is a thin wrapper over the exact URLs documented in these files.
* **One canonical library underneath.** Revenue, cost, margin, and MRR math runs through one shared library. The same numbers come out whether you hit an SDK method, a REST endpoint, or view the dashboard. There is no longer a "dashboard API vs public API" distinction: every consumer runs through the same canonical code path.

Example:

```bash theme={null}
curl https://api.marginfront.com/v1/customers \
  -H "x-api-key: $MF_API_SECRET_KEY"
```

***

## Legacy paths (still working during the deprecation window)

Two legacy URL shapes still resolve, backed by the same handlers as the new URLs:

* `/v1/org/:orgId/<resource>`: the old admin REST shape
* `/v1/sdk/<resource>`: the old SDK-surface shape

**Both still work.** The `@marginfront/sdk@0.5.0` npm package continues to function without any changes on your side. Existing integrations that hardcoded either URL shape will keep working.

**But:**

* The legacy paths are **not documented** in the per-resource doc files. Those files only describe the new canonical paths.
* The legacy paths will be **removed** after the deprecation window ends. When we pick a removal date, we'll announce it with enough runway for you to migrate.
* **New integrations should always use `/v1/<resource>`.** It's shorter, cleaner, and will outlive the legacy paths.

***

## Migrating existing integrations

If you're still on the old URL shapes, migration is a find-and-replace:

| Before                            | After                      |
| --------------------------------- | -------------------------- |
| `POST /v1/org/{orgId}/customers`  | `POST /v1/customers`       |
| `GET /v1/sdk/customers`           | `GET /v1/customers`        |
| `POST /v1/sdk/usage/record`       | `POST /v1/usage/record`    |
| `GET /v1/sdk/analytics/usage`     | `GET /v1/analytics/usage`  |
| `GET /v1/sdk/invoices`            | `GET /v1/invoices`         |
| `GET /v1/sdk/verify`              | `GET /v1/verify`           |
| `POST /v1/sdk/portal-sessions`    | `POST /v1/portal-sessions` |
| `Authorization: Bearer mf_sk_...` | `x-api-key: mf_sk_...`     |

Also: **drop any `MF_ORG_ID` env var you were passing into URLs.** You don't need it anymore.

***

## Why the unification happened

Historical reasons. Originally we had:

1. An **admin REST API** (`/v1/org/:orgId/*`) that the dashboard used internally. It required the URL to include the org ID because the dashboard knew which org the logged-in user was viewing.
2. An **SDK API** (`/v1/sdk/*`) that the `@marginfront/sdk` npm package called. It didn't need the org ID in the URL because the API key already identified the org.

When we opened the admin endpoints to API key auth (so customers could use them directly from their own code), customers ended up with two parallel surfaces to choose from. Having two was confusing, shipped too much surface area to document, and made the SDK harder to build and maintain.

The unify decision (2026-04-11) collapsed both into a single public API under `/v1/<resource>`, matching how Stripe, Anthropic, OpenAI, Resend, and every modern API-first company does it:

* **URL stability.** The URL shape doesn't change based on account state.
* **Less to remember.** One credential, one URL shape.
* **Fewer mistakes.** You can't accidentally hit one org's URL with another org's key.
* **Cleaner SDKs.** No `orgId` parameter cluttering every method signature.

***

## Questions?

Email `team@marginfront.com`. If something in the old docs still works but isn't documented in the new ones, that's a migration gap we want to know about.
