Skip to main content

Services Catalog

The services catalog is MarginFront’s record of every model and non-LLM service it can calculate cost for. When you fire a usage event with model and modelProvider, MarginFront looks up the catalog entry that matches and uses its rate to compute cost.
Use this endpoint to discover canonical names BEFORE firing events. If your service is in the catalog, send model: '<canonicalName>' and modelProvider: '<provider>' and cost auto-resolves on ingest. If not, the event still lands but cost stays null (NEEDS_COST_BACKFILL). The POST /v1/events/map-model endpoint can then redirect an unknown name to an existing catalog entry. It cannot create new rates.
The catalog is global. It is not org-scoped. Every authenticated caller sees the same entries. The catalog is read-only via the API. Entries are managed by an internal sync script that pulls from OpenRouter, LiteLLM, and a hand-curated list of non-LLM services.

List services

Returns paginated catalog entries. Filter by provider, service type, LLM-vs-non-LLM, or full-text search. Method & URL:
GET /v1/services
Headers:
x-api-key: mf_sk_...
Query parameters:
FieldTypeDescription
providerstringFilter by lowercase provider name (e.g. openai, google, anthropic, twilio). Case-insensitive.
serviceTypestringFilter by category (e.g. LLM, Geocoding, Compute, Web Search, Vector Database, SMS).
isApibooleanFilter to non-LLM API entries only (true) or LLM-only (false). Omit for both.
searchstringCase-insensitive search across canonicalName and displayName.
pageinteger1-based page number. Defaults to 1.
limitintegerPage size, 1 to 100. Defaults to 50.
Example: list every Google service
curl "https://api.marginfront.com/v1/services?provider=google" \
  -H "x-api-key: $MF_API_SECRET_KEY"
Example: find every non-LLM API in the Compute category
curl "https://api.marginfront.com/v1/services?serviceType=Compute&isApi=true" \
  -H "x-api-key: $MF_API_SECRET_KEY"
Example: search by name
curl "https://api.marginfront.com/v1/services?search=cloud-run" \
  -H "x-api-key: $MF_API_SECRET_KEY"
Response:
{
  "data": [
    {
      "id": "df3c1acd-fdc4-4f6c-9d84-99697ffb76a2",
      "externalId": "api/cloud-run-cpu-second",
      "canonicalName": "cloud-run-cpu-second",
      "displayName": "Google Cloud Run vCPU",
      "provider": "google",
      "serviceType": "Compute",
      "inputCost": "0.024",
      "outputCost": null,
      "costUnit": "1K vCPU-seconds",
      "contextWindow": null,
      "source": "curated",
      "isApi": true,
      "isActive": true
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 9,
    "totalPages": 1
  }
}
Field reference:
FieldDescription
idUUID of the catalog entry. Pass to GET /v1/services/:id for the full record.
externalIdSource-specific identifier (e.g. openai/gpt-4o, api/cloud-run-cpu-second, litellm/anthropic/claude-sonnet-4-20250514). Useful for tracing where the entry came from.
canonicalNameThe lowercase name to send as model in your usage events. This is what the cost lookup matches against.
displayNameHuman-readable name for UI surfaces. Not used for matching.
providerLowercase provider name to send as modelProvider.
serviceTypeCategory label (e.g. LLM, Geocoding, Compute).
inputCostPer-unit cost on the input side. Returned as a string-formatted decimal so JS Number precision can’t truncate fractional cents. null when the service does not publish an input-side rate.
outputCostPer-unit cost on the output side (LLM output tokens). null for non-LLM services.
costUnitUnit the rates are denominated in (e.g. 1M tokens, 1K requests, 1K vCPU-seconds).
contextWindowLLM context window size in tokens. null for non-LLM.
sourceWhere the entry came from: openrouter, litellm, or curated.
isApitrue for non-LLM API entries (Cloud Run, Twilio, Google Places, etc.). false for LLM models.
isActivefalse if the entry has been deactivated. The list endpoint filters these out by default.

Get a single service

GET /v1/services/:serviceId
Returns the full record for one catalog entry by its UUID. Same shape as one row in the list response. Example:
curl "https://api.marginfront.com/v1/services/df3c1acd-fdc4-4f6c-9d84-99697ffb76a2" \
  -H "x-api-key: $MF_API_SECRET_KEY"
Errors:
CodeCause
404The catalog entry does not exist or has been deactivated.
401Missing or invalid API key.

Using the catalog in your integration

Pattern that avoids the NEEDS_COST_BACKFILL cycle:
  1. Before adding a new service to your code, call GET /v1/services?search=<your-service-name> (or ?provider=<provider>).
  2. If the response has a matching entry, use its canonicalName as model and its provider as modelProvider.
  3. Fire usage events. Cost auto-resolves on ingest.
If no matching entry exists, two paths:
  • Map an existing entry. If your service is similar to one in the catalog (e.g. a Google Places sub-endpoint mapping to the bundled google-places entry), use POST /v1/events/map-model to redirect your unknown name to the existing entry. Cost backfills retroactively for events already saved with cost = null.
  • Catalog gap. If nothing in the catalog represents your service accurately, fire events anyway. Events are saved with cost = null and eventStatus = NEEDS_COST_BACKFILL. Email [email protected] with the service name and your provider’s pricing page; we’ll add it to the catalog.

Programmatic access

The same catalog is available via:
  • Node SDK: client.services.list(...) and client.services.get(id). Documented in the SDK reference.
  • MCP: the list_catalog_services tool. Documented in the MCP tools reference.