[Vision](https://compute.finance) | [Oracle](https://oracle.compute.finance) | [Documentation](https://docs.compute.finance)

---

# Compute Finance -- Documentation

API reference, guides, and integration documentation for Compute Finance.

---

## Early Access

Compute Finance is in early access.

The CPI Oracle and public API are live. Register a Compute Finance ID to join the waitlist.

[REQUEST ACCESS](https://compute.finance/login)

---

## What is the CPI?

The Compute Price Index ("CPI") is a public benchmark that tracks the cost of AI inference across major providers. It produces a single equal-weighted reference price -- the Standard Compute Unit ("SCU") -- calculated from a basket of 18 models across 9 providers.

### The Problem

LLM inference pricing is fragmented. Every provider quotes pricing differently — per token, per character, per request, per model. There is no standardized way to benchmark or compare the cost of AI computation across models and providers. You need a verifiable pricing reference you can audit independently.

### The Solution

The CPI is an equal-weighted basket of 18 AI models across 9 providers that produces a single, verifiable unit of account: the Standard Compute Unit (SCU). The SCU represents the USD cost of a fixed reference workload (token counts published via the API) taken as the geometric mean across the full basket.

### Key Properties

- **Verifiable** -- Basket composition and every basket member's input/output price are published on-chain via the OracleRegistry contract on Base, so anyone can independently verify the index. Cache and reasoning rates are live-catalog data and are not attested on-chain.
- **Diversified** -- 18 models across 9 providers prevent any single provider or model version from dominating the index.
- **Gaming-resistant by math** -- The Nth-root damping of the geometric mean and the one-family-one-slot rule prevent any single model or provider from dominating the index. No governance committee, no outlier caps.
- **Versioned** -- Every published revision permanently carries the methodology version that produced it. The active version is served by `GET /v1/oracle/methodology` and the `X-Methodology-Version` response header on every `/v1/oracle/*` response.
- **Open methodology** -- The formula is deterministic and reproducible from the public API (`weiPricePerMillion` field) and the methodology document.

---

## Basket Composition

The CPI tracks 18 models from 9 providers. Every model family gets one slot, the latest version always, and each model is weighted equally. A model family is a provider's distinct product line (for example `openai.gpt` and `openai.gpt-mini` are different families). The latest released model in each family is its representative; on a new release the representative auto-rolls. The basket is updated with a new version number when basket composition or provider rate-card prices change.

[Live data: GET https://api.compute.finance/v1/oracle/basket]

---

## SCU Formula

The Standard Compute Unit is calculated in two steps. The reference workload is a fixed token count (published in the `referenceWorkload` field of `GET https://api.compute.finance/v1/oracle/scu`), evaluated across all basket models. The full binding specification, including the exact fixed-point arithmetic, is published at `GET https://api.compute.finance/v1/oracle/methodology` and at the `specUrl` of each methodology record.

The SCU is reconstitution-driven. It is published on-chain whenever the basket changes, either because a model is added, removed, or replaced, or because a provider updates a rate-card price. Both triggers produce a new on-chain version. There is no fixed cadence and no continuous off-chain feed.

### Step 1 -- Per-model cost

For each model in the basket, compute the cost of the reference workload using the provider's published per-token pricing. Prices are USD per 1M tokens.

```
cost_m = (input_price_m x 0.001) + (output_price_m x 0.0005)
```

**Pricing source.** The API returns two price fields per model (via `GET /v1/oracle/basket`):

- `weiPricePerMillion` -- price in on-chain credit units, derived from the OracleRegistry contract. This is the source of truth used internally for SCU calculation.
- `usdPricePerMillion` -- USD value derived from `weiPricePerMillion x peg`, **rounded to 2 decimal places** for display. Not suitable for exact SCU reproduction.

To convert wei to USD: `usd_price = weiPricePerMillion x peg`, where `peg` is the `pegUsd` field from `GET /v1/oracle/pricing` -- no RPC call required. On-chain source: `Treasury.computePriceUsdc()` on Base (contract `0xB77DA11C8eC91D3417aA87072DcDD971A9aF674d`).

### Step 2 -- Equal-Weight Geometric Mean

The SCU is the geometric mean of all N model workload costs, each family weighted equally at 1/N. The Nth-root damping plus the one-family-one-slot rule provide gaming resistance by math — no outlier caps, no governance committee.

```
SCU = (∏ cost_m)^(1/N)   for all m in the index, N = 18
```

The binding arithmetic uses a floor Nth root over integer 18-decimal USD values — defined precisely in the methodology document so any independent re-implementation reproduces the published SCU bit-for-bit.

**Methodology versioning.** Every published revision permanently carries the methodology version that produced it (currently v1 = equal-weight geometric mean). The full changelog and per-version definitions are served by `GET /v1/oracle/methodology`; every `/v1/oracle/*` response also carries the `X-Methodology-Version` header reflecting the version in force now.

### Worked Example (exact reproduction)

```
# 1. Fetch basket, peg, and methodology workload
basket      = GET /v1/oracle/basket       → models[].weiPricePerMillion.{input, output}
pricing     = GET /v1/oracle/pricing      → pegUsd
methodology = GET /v1/oracle/methodology  → entries[0].referenceWorkload

# 2. Per-model cost: convert wei to USD, then reference-workload cost
peg          = pricing.pegUsd
input_usd_m  = model.weiPricePerMillion.input  x peg
output_usd_m = model.weiPricePerMillion.output x peg
cost_m       = (input_usd_m x 0.001) + (output_usd_m x 0.0005)

# 3. Equal-weight geometric mean over N representatives
SCU = (∏ cost_m)^(1/N)   for all m in the index, N = 18
```

---

## Governance

The model-family rule reduces governance to a minimum. One eligibility rule, one family rule, one emergency trigger. No weight committees, no tier reviews.

| Rule | Specification | Frequency |
| ---- | ------------- | --------- |
| Listing Criteria | Public GA + first-party USD pricing + in-scope text model + seasoning + liveness. Applied identically to all. | Continuous |
| Model Family Rule | One slot per family, latest GA version auto-wins. No governance needed. | Auto |
| Edge-Case Review | Published, dated decision for family-vs-version edge cases. Stated reasoning. | As Needed |
| Reconstitution | Additions and removals applied by the criteria. Logged. | Scheduled |
| Price Updates | Reflected automatically from first-party price cards. Daily scan. | Daily |
| Emergency Trigger | Any single model that moves price by more than the set threshold in 24 hours enters a short hold before the change is reflected. | As Needed |

**Revision numbering.** The API's `revisionVersion` and `latestRevisionVersion` fields return the on-chain revision counter -- a monotonically incrementing integer starting at 1 with the genesis revision. Each `/v1/oracle/*` response that includes `revisionVersion` reflects the on-chain revision number. The full history is available via the `GET https://api.compute.finance/v1/oracle/reconstitutions` endpoint and exportable as CSV.

---

## On-Chain Verification

All CPI pricing is recorded on-chain via the OracleRegistry contract on Base. You can independently verify prices without trusting the Compute Finance API.

Contract address, read functions, ethers.js examples, and Basescan verification instructions are maintained at the oracle subdomain: https://oracle.compute.finance/llms-full.txt#on-chain-verification

---

## Public API

All oracle endpoints are public and require no authentication. Read access is free and unrestricted. Base URL: `https://api.compute.finance`

### OpenAPI specification

The public API contract is published as an OpenAPI 3.x document — auto-generated from the live NestJS controllers, so the spec and the running server cannot drift. Use it to generate typed clients in any language with `openapi-generator`, `openapi-typescript`, `oapi-codegen`, or any other OpenAPI-driven codegen.

| URL | Format | Notes |
|---|---|---|
| `https://api.compute.finance/v1/openapi.yaml` | YAML | Canonical |
| `https://api.compute.finance/v1/openapi.json` | JSON | Same spec, JSON encoding |
| `https://api.compute.finance/openapi.yaml` | YAML | Conventional alias for agents probing root |
| `https://api.compute.finance/openapi.json` | JSON | Conventional alias |
| `https://api.compute.finance/openapi` | HTML | Swagger UI for interactive exploration |
| `https://api.compute.finance/v1/docs` | HTML | Same Swagger UI, versioned path |

All alias URLs return the same byte-identical body — there is exactly one public spec. Public-spec resource endpoints emit a `Link: <https://api.compute.finance/v1/openapi.yaml>; rel="service-desc"; type="text/yaml"` HTTP header (RFC 8631) pointing at the canonical spec. The spec endpoints themselves are reachable cross-origin (`Access-Control-Allow-Origin: *`) so browser-based agents can fetch directly. Cache control: `public, max-age=300, must-revalidate` with weak ETags from Express defaults — refetch periodically to pick up new endpoints when the API ships.

**Scope.** The public spec covers read-only Oracle (`/v1/oracle/*`) endpoints — twenty-two routes total. The paid **Inference API** (OpenAI- and Anthropic-compatible chat + messages, plus `/v1/models`, `/v1/usage`, `/v1/inference/estimate`) is published as a **separate spec** at [`/v1/openapi.inference.yaml`](https://api.compute.finance/v1/openapi.inference.yaml) with its own Swagger UI at [`/v1/docs/inference`](https://api.compute.finance/v1/docs/inference) and its human reference at [`docs.compute.finance/#inference-api`](https://docs.compute.finance/#inference-api); it is documented in the [Inference API section](#inference-api) below. Wallet-signed account / keys / treasury flows remain internal to first-party UIs.

**Discovery.** The OpenAPI URL is also referenced from `llms.txt` and `llms-full.txt` on `compute.finance`, `oracle.compute.finance`, and `docs.compute.finance`, listed once in the docs sitemap, and advertised in the HTML `<head>` of all three UIs as `<link rel="service-desc" type="text/yaml" href="…">`. Agents probing any of these surfaces should reach the spec without guessing paths.

### Rate limits

The public oracle API is rate-limited to **120 requests per minute per IP** (burst 120). A short-term cap of 5 requests per second and a medium-term cap of 20 requests per 10 seconds also apply to protect the backend. Every response includes `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers (from the NestJS Throttler). Clients that exceed the limit receive a `429 Too Many Requests` response with a `Retry-After` header. Data updates on reconstitution, so polling more often than once per minute is not useful.

**`/v1/points`** — the points and achievements API requires CF ID JWT authentication and is not yet part of the public API surface. It will be documented when publicly available.

### V1 scope -- what is not shipping

V1 does not ship a first-party typed SDK -- use the OpenAPI spec at `https://api.compute.finance/v1/openapi.yaml` to generate clients with `openapi-generator`, `openapi-typescript`, or `oapi-codegen`.

### Compute Finance MCP

The official Compute Finance MCP server is published at [github.com/compute-finance/mcp](https://github.com/compute-finance/mcp) and available as an npm package at [@compute-finance/mcp](https://www.npmjs.com/package/@compute-finance/mcp). Transport: stdio (local process, no hosted endpoint). No API key required.

Install in any MCP client:
```json
{ "command": "npx", "args": ["@compute-finance/mcp"] }
```

Claude Code one-liner (registers MCP + installs skills + cost hook):
```
npx @compute-finance/mcp setup
```

14 tools across five layers: data (basket, price, SCU, CPI, methodology, reconstitutions), compute (estimate, compare), render (session report, consumption report, active sessions), analysis (session, inferences), and history (telemetry). All tools are read-only.

---

## Endpoints

Paths are against `https://api.compute.finance`; `{key}`, `{revision}`, `{iso8601}` are RFC 6570 placeholders.

| Method | Path | Description |
|---|---|---|
| GET | `/v1/oracle/scu` | Current SCU value, reference workload, methodology version |
| GET | `/v1/oracle/models` | Catalog: basket models plus retired ex-members (`inBasket`, `retiredAtRevision`); retired models priced from the live catalog |
| GET | `/v1/oracle/models/{key}` | Single catalog model (basket member or retired) by pricing key |
| GET | `/v1/oracle/catalog` | Every tracked model with current price and index-member flag |
| GET | `/v1/oracle/models/{key}/price-at?date={iso8601}` | Per-model input/output USD price effective at the requested timestamp (`source: "manifest"` for basket members, `source: "catalog"` otherwise) |
| GET | `/v1/oracle/basket` | Full basket composition (models + SCU value + routing fee + revision/methodology version) |
| GET | `/v1/oracle/history?from={iso8601}&to={iso8601}&granularity={per-revision\|daily\|weekly}&limit={int}` | SCU index time series; `Accept: text/csv` returns a CSV attachment |
| GET | `/v1/oracle/models/{key}/price-history?from={iso8601}&to={iso8601}&granularity={per-revision\|daily\|weekly}&limit={int}` | Per-model input/output USD price time series; `Accept: text/csv` returns a CSV attachment |
| GET | `/v1/oracle/reconstitutions` | History of basket reconstitutions with version, models, SCU delta |
| GET | `/v1/oracle/revisions/{revision}` | Full OracleRevision record for a specific on-chain revision |
| GET | `/v1/oracle/health` | Latest confirmed revision version and confirmation timestamp |
| GET | `/v1/oracle/contract-metadata` | Live OracleRegistry identity — chainId, proxy address, on-chain `version()`, and `keccak256` of the deployed bytecode |
| GET | `/v1/oracle/baseline` | Frozen SCU of the first confirmed revision — denominator for the inverse `computeIndex` purchasing-power view |
| GET | `/v1/oracle/scu-at?date={iso8601}` | SCU value active at a given timestamp — step-function lookup of the latest confirmed revision with `publishedAt ≤ date` |
| GET | `/v1/oracle/latest` | Latest confirmed revision summary (version, SCU, basket size) |
| GET | `/v1/oracle/stats` | Aggregate protocol statistics |
| GET | `/v1/oracle/activity?limit=50&offset=0` | Paginated activity feed |
| GET | `/v1/oracle/pricing` | Per-model pricing in $COMPUTE (wei) and USD |
| GET | `/v1/oracle/methodology` | Active methodology version + full changelog |
| GET | `/v1/oracle/methodology/{version}` | Single methodology record (formula, reference workload, family rule, spec URL) |
| GET | `/v1/oracle/manifest/{metadataHash}` | Content-addressed manifest for a confirmed revision (`metadataHash` = JCS+keccak256 of the whole document; `contentHash` = of the price projection) |
| GET | `/v1/oracle/reconstitutions/export` | Reconstitution history as downloadable markdown |

Every `/v1/oracle/*` response carries the `X-Methodology-Version` header reflecting the methodology version in force at request time.

**`/v1/oracle/models` vs `/v1/oracle/basket`**: The `/models` endpoint returns the catalog array — current basket members (`inBasket: true`) plus retired ex-members (`inBasket: false`, `retiredAtRevision` set, priced from the live catalog). The `/basket` endpoint returns only current members PLUS basket-level metadata: SCU value in USD, routing fee rate, revision version, methodology version, and last-updated timestamp.

---

## Code Examples

All endpoints are public. No authentication required.

### Get Current SCU

**cURL**

```bash
curl https://api.compute.finance/v1/oracle/scu
```

**Python**

```python
import requests

resp = requests.get("https://api.compute.finance/v1/oracle/scu")
data = resp.json()
print(f"SCU: {data['scuUsd']}")
```

**TypeScript**

```typescript
const resp = await fetch("https://api.compute.finance/v1/oracle/scu");
const data = await resp.json();
console.log(`SCU: ${data.scuUsd}`);
```

### List All Models

**cURL**

```bash
curl https://api.compute.finance/v1/oracle/models
```

**Python**

```python
import requests

resp = requests.get("https://api.compute.finance/v1/oracle/models")
data = resp.json()
for model in data["models"]:
    print(f"{model['displayName']} ({model['family']})")
```

**TypeScript**

```typescript
const resp = await fetch("https://api.compute.finance/v1/oracle/models");
const data = await resp.json();
for (const model of data.models) {
  console.log(`${model.displayName} (${model.family})`);
}
```

### Get Single Model

**cURL**

```bash
curl https://api.compute.finance/v1/oracle/models/claude-opus-5
```

**Python**

```python
import requests

resp = requests.get("https://api.compute.finance/v1/oracle/models/claude-opus-5")
model = resp.json()
print(f"{model['displayName']}: ${model['usdPricePerMillion']['input']}/1M input")
```

**TypeScript**

```typescript
const resp = await fetch("https://api.compute.finance/v1/oracle/models/claude-opus-5");
const model = await resp.json();
console.log(`${model.displayName}: $${model.usdPricePerMillion.input}/1M input`);
```

### Historical SCU (date range)

**cURL**

```bash
curl "https://api.compute.finance/v1/oracle/history?from=2026-05-18T00:00:00Z&to=2026-06-18T00:00:00Z&granularity=daily"
curl -H "Accept: text/csv" "https://api.compute.finance/v1/oracle/history?from=2026-05-18T00:00:00Z&to=2026-06-18T00:00:00Z&granularity=daily" -o scu-history.csv
```

**Python**

```python
import requests

resp = requests.get(
    "https://api.compute.finance/v1/oracle/history",
    params={"from": "2026-05-18T00:00:00Z", "to": "2026-06-18T00:00:00Z", "granularity": "daily"},
)
data = resp.json()
for point in data["data"]:
    print(f"{point['date']}: SCU={point['scuUsd']} (revision {point['revisionVersion']})")
```

**TypeScript**

```typescript
const resp = await fetch(
  "https://api.compute.finance/v1/oracle/history?from=2026-05-18T00:00:00Z&to=2026-06-18T00:00:00Z&granularity=daily",
);
const data = await resp.json();
for (const point of data.data) {
  console.log(`${point.date}: SCU=${point.scuUsd} (revision ${point.revisionVersion})`);
}
```

---

## Response Schemas

Paths are against `https://api.compute.finance`; `{revision}` and `{iso8601}` are RFC 6570 placeholders.

### `GET /v1/oracle/scu`

The live SCU value, reference workload, active methodology version, and the per-family breakdown. The `breakdown` field is a discriminated union keyed by `methodologyVersion`: under v1 it carries the list of family representatives, each with the family key, model key, USD-per-million-token input/output prices, and the blended cost over the reference workload. The empty-basket case returns `204 No Content`. Example values are illustrative — fetch the live endpoint for current numbers.

```json
{
  "scuUsd": 0.002435,
  "computeIndex": 100.00,
  "referenceWorkload": { "inputTokens": 1000, "outputTokens": 500 },
  "methodologyVersion": 1,
  "breakdown": {
    "methodologyVersion": 1,
    "familyRepresentatives": [
      {
        "family": "openai.gpt",
        "modelKey": "gpt-5.5",
        "inputPriceUsdPerMillion": 5.0,
        "outputPriceUsdPerMillion": 30.0,
        "blendedCostUsd": 0.02
      }
    ]
  },
  "updatedAt": "2026-06-18T12:00:00.000Z"
}
```

`computeIndex` is the inverse purchasing-power index `(baseline / scuUsd) × 100`, a display/foundation-grade derived field — `100` at genesis, rises as compute gets cheaper, falls as it gets more expensive. The baseline denominator is published at `/v1/oracle/baseline` and frozen at the first confirmed revision's SCU. `null` only when the baseline has not been published yet.

### `GET /v1/oracle/models`

The full list of basket models. The response is a top-level `models` array; each entry carries the model identity, family, integration status, both raw and marked-up per-million pricing in $COMPUTE and USD, and per-model `cache` / `reasoning` multiplier blocks. The multiplier blocks are catalog/metering data — they do not enter the SCU formula. Example values are illustrative.

```json
{
  "models": [
    {
      "id": "gpt-5.5",
      "displayName": "GPT-5.5",
      "provider": { "key": "openai", "name": "OpenAI" },
      "family": "openai.gpt",
      "weiPricePerMillion": { "input": "756430000000000000000", "output": "4538580000000000000000" },
      "usdPricePerMillion": { "input": 5.0, "output": 30.0 },
      "markedUpWeiPricePerMillion": { "input": "794252000000000000000", "output": "4765509000000000000000" },
      "markedUpUsdPricePerMillion": { "input": 5.25, "output": 31.5 },
      "releasedAt": "2026-04-01T00:00:00Z",
      "cache": {
        "cachedInput": { "usdPerMillion": 0.5, "ratioOfInput": 0.1, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "cacheWrite5m": { "usdPerMillion": 5.0, "ratioOfInput": 1.0, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "cacheWrite1h": { "usdPerMillion": 5.0, "ratioOfInput": 1.0, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "read_multiplier": 0.1,
        "write_multiplier_5m": 1.0,
        "write_multiplier_1h": 1.0
      },
      "reasoning": null
    }
  ]
}
```

**Field: `releasedAt`** -- ISO 8601 timestamp of the model's public release; `null` if unknown. **Field: `cache`** -- cached-input + cache-write multiplier block; each entry carries both `usdPerMillion` and `ratioOfInput`, plus flat `read_multiplier` / `write_multiplier_5m` / `write_multiplier_1h` shortcuts at the block level. `null` when the model has no cache multiplier data. **Field: `reasoning`** -- reasoning-output multiplier block; `null` when the provider bills thinking tokens at the standard output rate (no distinct reasoning surcharge). Both blocks are served from the live catalog (`source: "catalog"`, `sourceUrl: null`) and are never attested on-chain -- the manifest carries basket `input`/`output` only. `createdAt` is the catalog observation time, or `null` when it is unknown.

### `GET /v1/oracle/basket`

Full basket composition: models array plus SCU value, routing fee rate, revision/methodology version, and last-updated timestamp.

```json
{
  "models": [
    {
      "id": "claude-opus-5",
      "displayName": "Claude Opus 5",
      "provider": { "key": "anthropic", "name": "Anthropic" },
      "family": "anthropic.claude",
      "weiPricePerMillion": { "input": "756430000000000000000", "output": "3782150000000000000000" },
      "usdPricePerMillion": { "input": 5.0, "output": 25.0 },
      "markedUpWeiPricePerMillion": { "input": "794252000000000000000", "output": "3971257000000000000000" },
      "markedUpUsdPricePerMillion": { "input": 5.25, "output": 26.25 },
      "releasedAt": "2026-05-01T00:00:00Z",
      "cache": null,
      "reasoning": null
    }
  ],
  "scuUsd": 0.002435,
  "routingFeeRate": 0.05,
  "revisionVersion": 1,
  "methodologyVersion": 1,
  "lastUpdated": "2026-06-18T12:00:00Z"
}
```

### `GET /v1/oracle/history?from={iso8601}&to={iso8601}&granularity={per-revision|daily|weekly}&limit={int}`

SCU index time series over the requested range. `granularity` defaults to `per-revision`; `daily` and `weekly` buckets carry the last revision's value forward across empty buckets (step-function close). `limit` caps the series at 10000 points; oldest points are dropped first and `truncated: true` is set. Each point carries the revision and methodology version active at that bucket plus the `metadataHash` of the revision that produced it -- fetch `GET /v1/oracle/manifest/{metadataHash}` to verify the per-family breakdown for that point. Set `Accept: text/csv` to download a spreadsheet-friendly CSV with columns `date,scuUsd,computeIndex,revisionVersion,methodologyVersion,metadataHash` instead of JSON.

```json
{
  "from": "2026-06-18T00:00:00.000Z",
  "to": "2026-07-18T00:00:00.000Z",
  "granularity": "daily",
  "count": 31,
  "truncated": false,
  "data": [
    { "date": "2026-06-18T00:00:00.000Z", "scuUsd": 0.002435, "computeIndex": 100.00, "revisionVersion": 1, "methodologyVersion": 1, "metadataHash": "0x4f5b..." },
    { "date": "2026-07-18T00:00:00.000Z", "scuUsd": 0.002418, "computeIndex": 100.70, "revisionVersion": 2, "methodologyVersion": 1, "metadataHash": "0x7e2a..." }
  ]
}
```

### `GET /v1/oracle/models/{key}/price-history?from={iso8601}&to={iso8601}&granularity={per-revision|daily|weekly}&limit={int}`

Input/output USD-per-million-token price time series. Every point carries a `source`. For a model that has appeared in at least one confirmed revision's basket the series is manifest-sourced (`source: "manifest"`, each point cross-linking `revisionVersion` / `methodologyVersion` / `metadataHash`), with the same range, granularity, limit, and `Accept: text/csv` semantics as `/v1/oracle/history`; `family` echoes the family slot the model occupies in its most recent appearance, and catchup revisions whose manifest is not yet available are surfaced in `unavailableRevisions`. Any other tracked model falls back to the live catalog's temporal history — `source: "catalog"`, one point per price change, `unavailableRevisions: []`, and `family` may be `null`. Models with neither a basket appearance nor a catalog price return `404 not_found`.

```json
{
  "modelKey": "gpt-5.5",
  "family": "openai.gpt",
  "from": "2026-06-18T00:00:00.000Z",
  "to": "2026-07-18T00:00:00.000Z",
  "granularity": "daily",
  "count": 31,
  "truncated": false,
  "unavailableRevisions": [],
  "data": [
    { "date": "2026-06-18T00:00:00.000Z", "inputPriceUsdPerMillion": 5.0, "outputPriceUsdPerMillion": 30.0, "source": "manifest", "revisionVersion": 1, "methodologyVersion": 1, "metadataHash": "0x4f5b..." },
    { "date": "2026-07-18T00:00:00.000Z", "inputPriceUsdPerMillion": 5.0, "outputPriceUsdPerMillion": 30.0, "source": "manifest", "revisionVersion": 2, "methodologyVersion": 1, "metadataHash": "0x7e2a..." }
  ]
}
```

### `GET /v1/oracle/catalog`

Display/reporting-grade catalog of every tracked model. Each entry carries identity, provider, family, the `indexMember` flag (`true` when the model is the current family representative in the latest confirmed revision's manifest), the current input/output USD price per million tokens with the `observedAt` timestamp from the underlying live-catalog (`ModelPrice`) row, and the per-model `cache` / `reasoning` blocks when present. Models without a live catalog price are excluded. The series is capped at 1000 entries; if exceeded, oldest are dropped and `truncated: true` is set. `Cache-Control: public, max-age=60`.

```json
{
  "models": [
    {
      "modelKey": "gpt-5.5",
      "displayName": "GPT-5.5",
      "provider": { "key": "openai", "name": "OpenAI" },
      "family": "openai.gpt",
      "indexMember": true,
      "releasedAt": "2026-01-15T00:00:00.000Z",
      "currentPrice": {
        "inputPriceUsdPerMillion": 1.25,
        "outputPriceUsdPerMillion": 10.0,
        "observedAt": "2026-06-10T08:30:00.000Z"
      },
      "cache": null,
      "reasoning": null
    }
  ],
  "truncated": false,
  "generatedAt": "2026-06-17T12:34:56.789Z"
}
```

### `GET /v1/oracle/models/{key}/price-at?date={iso8601}`

Per-model input/output USD price effective at the requested timestamp. The response is a discriminated union keyed by `source`: `"manifest"` when the model is the family representative in the revision active at that date (cross-links `revisionVersion`, `methodologyVersion`, `metadataHash`, and `family` so a caller can fetch and verify the full manifest), or `"catalog"` when the model was not a basket member at that date — the answer then comes from the live catalog's temporal history (step-function: the `ModelPrice` range covering the date), and `family` may be `null`. `observedAt` reflects when the price was recorded, not request time. Returns `422 validation_failed` if the date is malformed or in the future, `404 not_found` for untracked models, and `404 not_found` when neither the attested manifest nor the live catalog has a price at that date. `Cache-Control: public, max-age=60`.

```json
{
  "source": "manifest",
  "modelKey": "gpt-5.5",
  "date": "2026-06-15T12:00:00Z",
  "inputPriceUsdPerMillion": 1.25,
  "outputPriceUsdPerMillion": 10.0,
  "observedAt": "2026-06-11T10:00:00.000Z",
  "revisionVersion": 7,
  "methodologyVersion": 1,
  "metadataHash": "0x38551a40...",
  "family": "openai.gpt"
}
```

### `GET /v1/oracle/methodology`

Active methodology version and the full changelog. Each entry pins the formula identity, family rule, reference workload, and `specUrl` of the published methodology document.

```json
{
  "activeVersion": 1,
  "entries": [
    {
      "version": 1,
      "title": "Equal-weight geometric mean of model-family representatives",
      "meanType": "geometric",
      "weighting": "equal-1-over-n",
      "familyRule": {
        "oneFamilyOneSlot": true,
        "familyKeyScheme": "provider.product-line",
        "representativeSelection": "latest-published-then-highest-revision"
      },
      "referenceWorkload": { "inputTokens": 1000, "outputTokens": 500 },
      "cacheReasoningInIndex": false,
      "formulaSummary": "SCU = (∏ cost_m)^(1/N) for all m in the index, equal weight 1/N; cost_m = inputUsdPerM × 0.001 + outputUsdPerM × 0.0005 in USD — no tiers, no provider weights, no outlier cap",
      "rationale": "Every model family counts equally toward the price: the Nth-root damping of the geometric mean plus the one-family-one-slot rule provide gaming resistance without tier weights or governed caps",
      "specUrl": "https://docs.compute.finance/methodology"
    }
  ]
}
```

### `GET /v1/oracle/revisions/{revision}`

Full OracleRevision record for a specific on-chain revision.

```json
{
  "revisionVersion": 1,
  "methodologyVersion": 1,
  "publishedAt": "2026-06-18T00:00:00.000Z",
  "publishedBlock": 31200000,
  "txHash": "0xabc…",
  "scuUsd": 0.002435,
  "scuUsd18": "2435000000000000",
  "basketSize": 18,
  "basket": {
    "schemaVersion": 1,
    "models": [
      {
        "modelKey": "gpt-5.5",
        "family": "openai.gpt",
        "inputPrice": "756430000000000000000",
        "outputPrice": "4538580000000000000000",
        "displayName": "GPT-5.5",
        "providerKey": "openai",
        "sdkId": "gpt-5.5-20260301"
      }
    ]
  },
  "status": "CONFIRMED",
  "confirmedAt": "2026-06-18T00:01:00.000Z",
  "manifestUrl": "<api-host>/v1/oracle/manifest/0x…"
}
```

### `GET /v1/oracle/reconstitutions`

Reconstitution event log with per-event change details.

```json
{
  "entries": [
    {
      "id": "recon-1",
      "revisionVersion": 1,
      "previousVersion": null,
      "publishedAt": "2026-06-18T00:00:00Z",
      "methodologyVersion": 1,
      "summary": "Inaugural equal-weighted basket v1.0",
      "scuBefore": null,
      "scuAfter": 0.002435,
      "changes": [
        { "type": "ModelAdded", "modelKey": "gpt-5.5", "description": "Added gpt-5.5 to the basket" },
        { "type": "ModelAdded", "modelKey": "claude-opus-5", "description": "Added claude-opus-5 to the basket" }
      ],
      "txHash": "0xabc123..."
    }
  ]
}
```

### `GET /v1/oracle/health`

Latest revision version and confirmation timestamp. `stale` is `true` if the last oracle sync is older than the configured threshold. `pendingRevision` carries `{ ageMs }` while a publish has been broadcast and is still awaiting on-chain confirmation, and `null` otherwise -- the field never leaks the pending revision's version, contentHash, or txHash.

```json
{
  "latestRevisionVersion": 23,
  "methodologyVersion": 1,
  "latestRevisionConfirmedAt": "2026-06-25T13:54:38.820Z",
  "lastSyncAt": "2026-07-18T10:15:30.000Z",
  "stale": false,
  "pendingRevision": null
}
```

### `GET /v1/oracle/contract-metadata`

Live identity read of the deployed `OracleRegistry` proxy. The backend reads the contract's on-chain `version()` and the `keccak256` of the deployed bytecode (`eth_getCode` then hashed) over the standard RPC the backend already uses for sync and publish. `bytecodeHash` is `null` when the contract has no deployed code or when the RPC call fails. Backend caches the response for five minutes; `Cache-Control: public, max-age=300`. Role membership is not exposed: the deployed `OracleRegistry` uses `AccessControl` without the `Enumerable` extension, so holders cannot be enumerated through the contract ABI — query the chain directly (BaseScan, event index) to inspect role grants.

```json
{
  "chainId": 8453,
  "address": "0x1b91c0961928a14a2eD6c1985bC11aF1b302714D",
  "version": 1,
  "bytecodeHash": "0x9c5b0e1a8b9d7e2a3c1d4f5e6a7b8c9d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f7",
  "checkedAt": "2026-06-19T11:00:00.000Z"
}
```

### `GET /v1/oracle/baseline`

The frozen SCU denominator for the inverse `computeIndex` purchasing-power view: the SCU of the first confirmed revision (methodologyVersion 1), captured set-once and never changes. The index reads `100` at genesis and rises as compute gets cheaper. Returns 204 No Content if no confirmed revision exists yet.

```json
{
  "date": "2026-06-18",
  "scuUsd": 0.002435,
  "methodologyVersion": 1
}
```

### `GET /v1/oracle/scu-at?date={iso8601}`

SCU value active at a given timestamp — a step function over the confirmed revision series. Resolves the latest revision with `publishedAt ≤ date` and returns its SCU, methodology version, revision version, publish timestamp, and metadataHash. When two confirmed revisions share `publishedAt` the highest `revisionVersion` wins (monotonicity is non-strict). `date` must be a full ISO-8601 instant with timezone offset. Responses:

- **200** — JSON with the active revision and the derived `computeIndex` (same `(baseline.scuUsd / scuUsd) × 100` formula as `/v1/oracle/scu` and `/v1/oracle/history`).
- **204** — `date` precedes the genesis revision.
- **422** — `date` is in the future, malformed, or missing the time component.

```json
{
  "at": "2026-06-18T12:00:00.000Z",
  "scuUsd": 0.002435,
  "scuUsd18": "2435000000000000",
  "computeIndex": 100.00,
  "revisionVersion": 1,
  "methodologyVersion": 1,
  "publishedAt": "2026-06-18T00:00:00.000Z",
  "metadataHash": "0x38551a40a8bcee07ccd31e1c062c23d8240acb3facd7ab0518b5b54df2fc5b3d"
}
```

### `GET /v1/oracle/latest`

Lightweight summary of the latest confirmed revision — no full basket payload. Returns 204 No Content if no confirmed revision exists yet.

```json
{
  "revisionVersion": 1,
  "methodologyVersion": 1,
  "publishedAt": "2026-06-18T00:00:00.000Z",
  "confirmedAt": "2026-06-18T00:01:00.000Z",
  "scuUsd": 0.002435,
  "computeIndex": 100.00,
  "basketSize": 18,
  "workload": { "inputTokens": 1000, "outputTokens": 500 },
  "metadataHash": "0x4f5b..."
}
```

### `GET /v1/oracle/pricing`

Per-model pricing in both $COMPUTE (wei per million tokens) and USD. `pegUsd` is the current $COMPUTE price. `cache` / `reasoning` blocks carry the same multiplier shape as on `/v1/oracle/models`; `null` when the model has no multiplier data for that block.

```json
{
  "object": "pricing",
  "pegUsd": 0.00661,
  "models": {
    "gpt-5.5": {
      "input": { "weiPerMillion": 227, "usdPerMillion": 1.5 },
      "output": { "weiPerMillion": 908, "usdPerMillion": 6.0 },
      "cache": {
        "cachedInput": { "usdPerMillion": 0.15, "ratioOfInput": 0.1, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "cacheWrite5m": { "usdPerMillion": 1.5, "ratioOfInput": 1.0, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "cacheWrite1h": { "usdPerMillion": 1.5, "ratioOfInput": 1.0, "source": "catalog", "sourceUrl": null, "createdAt": "2026-06-15T09:00:00Z" },
        "read_multiplier": 0.1,
        "write_multiplier_5m": 1.0,
        "write_multiplier_1h": 1.0
      },
      "reasoning": null
    }
  },
  "updatedAt": "2026-07-18T10:15:30Z"
}
```

---

## Inference API

Paid, OpenAI- and Anthropic-compatible inference over pooled provider capacity, billed against `$COMPUTE` held in BuyerEscrow at the metered rate published by the Oracle. This is a **separate product** from the free Oracle API above and is published as its own OpenAPI spec.

**Machine surface.**
- YAML — https://api.compute.finance/v1/openapi.inference.yaml
- JSON — https://api.compute.finance/v1/openapi.inference.json
- Swagger UI — https://api.compute.finance/v1/docs/inference
- Get a key — https://compute.finance/dashboard/api-keys

### Base URL and Authentication

Base URL: `https://api.compute.finance`. Auth: `Authorization: Bearer ct_live_<...>` on every endpoint. `POST /v1/messages` additionally accepts `x-api-key: ct_live_<...>` so the official `@anthropic-ai/sdk` works with only a base-URL swap (its default auth header is `x-api-key`).

Key state → response:
- `active` → normal responses.
- `frozen` → `403 API_KEY_FROZEN`. Ops-triggered; the key is temporarily suspended.
- `revoked` → `401 API_KEY_REVOKED`. Permanent, user-initiated.
- unknown / malformed → `401 INVALID_API_KEY`.

Model allowlist per key: if `apiKey.allowedModels` is non-empty and the request references a model not in that list → `403 MODEL_RESTRICTED`.

### Endpoints

| Method | Path | Auth | Description |
|---|---|---|---|
| `POST` | `/v1/chat/completions` | `Bearer ct_live_*` | OpenAI Chat Completions wire format. Streaming + non-streaming, tools, tool_choice, response_format (`text` \| `json_object` \| `json_schema`). |
| `POST` | `/v1/messages` | `Bearer ct_live_*` or `x-api-key` | Anthropic Messages API wire format. Streaming + non-streaming, tools, tool_choice, system prompts, cache_control. |
| `GET` | `/v1/models` | none | OpenAI-format catalog of routable models (`id`, `owned_by`, `routingAliases`). Cached 60s. |
| `GET` | `/v1/usage` | `Bearer ct_live_*` | Per-key balance and cumulative counters (daily / weekly / monthly limits + used). |
| `GET` | `/v1/inference/estimate?model=&promptTokens=&completionTokens=` | none | Pre-flight cost preview. Returns `creditsCost`, `creditsWei`, `usdCost`. Rate-limited to 10 req/s. |

### Wire-format compatibility deltas

Both endpoints route through the same provider pool. Compute Finance validates fail-loud on unsupported params (returns `422 VALIDATION_FAILED`) rather than silently dropping them, so integration bugs surface early.

**OpenAI Chat Completions.** Supported: `model`, `messages`, `stream`, `temperature`, `max_tokens`, `max_completion_tokens`, `top_p`, `stop`, `frequency_penalty`, `presence_penalty`, `seed`, `logit_bias`, `user`, `logprobs`, `top_logprobs`, `reasoning_effort`, `response_format` (`text` / `json_object` / `json_schema`), `tools`, `tool_choice`, `parallel_tool_calls`. Compute Finance additions: `models` (ordered fallback list, 1–8 entries), `conversation_id`. **Not supported (422):** `functions` / `function_call` (legacy — use `tools` / `tool_choice`), `n > 1` (single completion only), multimodal `content` arrays (out of scope for V1).

**Anthropic Messages.** Supported: `model`, `messages`, `max_tokens`, `system`, `metadata.user_id`, `stop_sequences`, `stream`, `temperature`, `top_p`, `top_k`, `tools`, `tool_choice`, content blocks (`text`, `tool_use`, `tool_result`), `cache_control`. Compute Finance additions: `models` (ordered fallback list). Extra fields on message objects are rejected (`.strict()` mode).

**Client fallback list (`models[]`).** Send `models` — an ordered list of catalogue ids (1–8). `model`, when present, is tried first, then each entry in turn; an entry lacking capacity or a requested capability is skipped. The request is billed at the model that answered (the pre-authorization covers the costliest listed entry; the excess is released at settlement), and the served model is reported in the response body and the `X-Model-Used` header in catalogue identifiers. Combining `models` with `model: "auto"` is rejected. Limitations: a prompt exceeding an entry's context window, or a parameter an entry rejects as invalid, aborts the request rather than falling through — fall-through covers capacity and capability, not `422`-class input errors.

**Provider capability gating.** Advanced features (tools, structured outputs) only work on providers that support them natively — currently `openai` and `anthropic`. A single named model on another provider returns `422 VALIDATION_FAILED`; inside a `models[]` list, such an entry is skipped and the request fails only if no listed entry supports the feature.

### Streaming

Both endpoints support Server-Sent Events (`Accept: text/event-stream`) when `stream: true`. Wire formats differ per SDK contract.

**OpenAI (`/v1/chat/completions`).**
```
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
...
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":5,"total_tokens":15},"x_credits_used":"...","x_credits_remaining":"...","x_ratelimit_requests_remaining":123}
data: [DONE]
```

**Anthropic (`/v1/messages`).** Named events per the Anthropic Messages streaming protocol:
```
event: message_start
data: {"type":"message_start","message":{"id":"msg_...","type":"message","role":"assistant","content":[],"model":"...","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":10,"output_tokens":0}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":5}}

event: message_stop
data: {"type":"message_stop"}
```

Stop reasons are translated between wire formats: OpenAI's `stop` ↔ Anthropic's `end_turn`, `length` ↔ `max_tokens`, `tool_calls` ↔ `tool_use`.

### Response headers

Every inference response (streaming and non-streaming) includes:

- `X-Compute-Used` — actual credits debited for this request, in wei.
- `X-Compute-Remaining` — buyer's remaining `$COMPUTE` balance after settlement, in wei.
- `X-Key-Daily-Remaining` / `X-Key-Weekly-Remaining` / `X-Key-Monthly-Remaining` — per-key spending cap remainder in wei, or `unlimited` if the corresponding cap is not set.
- `X-RateLimit-Limit` / `X-RateLimit-Remaining` / `X-RateLimit-Reset` — canonical rate-limit trio for the tightest active bucket.

Streaming final chunk mirrors the compute values into the body as `x_credits_used`, `x_credits_remaining`, `x_ratelimit_requests_remaining` for clients that consume streams without inspecting headers.

### Errors

Shared envelope:
```json
{
  "error": {
    "message": "human-readable summary",
    "type": "invalid_request_error | rate_limit_error | insufficient_quota | forbidden | server_error",
    "code": "INVALID_API_KEY | VALIDATION_FAILED | INSUFFICIENT_BALANCE | ...",
    "param": "field name — optional, present when the error is bound to input",
    "details": { "...": "code-specific structured payload" },
    "issues": [ "per-field validation errors, present on VALIDATION_FAILED" ]
  }
}
```

Inference-relevant codes:

| Code | Status | When |
|---|---|---|
| `INVALID_API_KEY` | 401 | Missing / malformed / unknown key. |
| `API_KEY_REVOKED` | 401 | Key was revoked by the owner. |
| `API_KEY_FROZEN` | 403 | Key is administratively frozen. |
| `MODEL_RESTRICTED` | 403 | Requested model is not in the key's `allowedModels`. |
| `VALIDATION_FAILED` | 422 | Request body failed validation; per-field details are in `error.issues[]`. Also raised for unsupported params (`functions`, `n > 1`, multimodal arrays) and provider-capability mismatch. |
| `METHOD_NOT_ALLOWED` | 405 | Endpoint exists but this HTTP method is not accepted (e.g. `GET` on `POST /v1/chat/completions`). The `Allow` response header lists the accepted methods. |
| `INSUFFICIENT_BALANCE` | 402 | Buyer's `$COMPUTE` balance cannot cover the reserve estimate. |
| `SPENDING_LIMIT_REACHED` | 429 | Per-key daily / weekly / monthly cap hit. `details: { scope, cap }`. |
| `RATE_LIMITED` | 429 | Per-pool RPM/TPM cap hit. |
| `ALL_KEYS_EXHAUSTED` | 502 | No healthy provider key available for the routed model. |
| `STREAM_INTERRUPTED` | 500 | Connection dropped mid-stream after provider ack. Reservation released; retry idempotently is safe. |
| `SERVICE_UNAVAILABLE` | 503 | Backing dependency (Oracle, Redis, provider gateway) is degraded. |

### Rate limits

Two independent limiter tiers apply to `/v1/chat/completions` and `/v1/messages`:

- **Per-key spending caps.** Daily / weekly / monthly caps on `$COMPUTE` spend, configured per API key. Exceeding a cap returns `429 SPENDING_LIMIT_REACHED` with `details: { scope: "key", cap: "daily" | "weekly" | "monthly" }`. Current remainder is surfaced in `X-Key-*-Remaining` headers.
- **Per-pool RPM/TPM.** Provider-pool-level ceilings enforced atomically on 1-minute buckets. Exceeding returns `429 RATE_LIMITED`.

`GET /v1/inference/estimate` is throttled to **10 requests per second per source IP**; it requires no authentication and does not consume `$COMPUTE`.

### Billing

Every inference request follows a **reserve-then-settle** flow:

1. Estimate input token count from `messages`. Estimated output = `max_completion_tokens ?? max_tokens ?? 4096`.
2. Convert `(input, output, model)` to credits at the Oracle's metered rate plus a 5% routing markup, expressed in wei.
3. Reserve the estimated wei against the account balance. An insufficient balance returns `402 INSUFFICIENT_BALANCE`; hitting a per-key or per-account spending cap returns `429 SPENDING_LIMIT_REACHED`.
4. Route to the provider, stream or receive the response, capture actual usage.
5. Settle the reservation: release the estimate, charge the actual metered cost, and update the per-key and per-account usage counters. Settlement always charges what the request actually used, so a request whose real cost outruns its estimate can leave the balance negative; the next request is refused with `402 INSUFFICIENT_BALANCE` until the account is topped up.

Response headers `X-Compute-Used` and `X-Compute-Remaining` report the final debit and remaining balance.

### Models

`GET /v1/models` returns the routable catalog in OpenAI wire format:
```json
{
  "object": "list",
  "data": [
    {
      "id": "openai/gpt-5.5",
      "object": "model",
      "created": 1732000000,
      "owned_by": "openai",
      "displayName": "OpenAI GPT-5.5",
      "routingAliases": ["gpt-5.5", "gpt5.5"]
    }
  ]
}
```

`id` is the `pricingKey` — the primary identifier for pricing and routing. `routingAliases` are shortcuts accepted by the router. Setting `model: "auto"` (or omitting `model`) triggers content-based auto-routing.

### Quickstarts

**Python (openai SDK, pinned to 2.45).**
```python
from openai import OpenAI

client = OpenAI(
    base_url="https://api.compute.finance/v1",
    api_key="ct_live_...",
)

resp = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)
```

**TypeScript (openai SDK, pinned to ^4.76).**
```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.compute.finance/v1",
  apiKey: process.env.COMPUTE_FINANCE_API_KEY!, // ct_live_...
});

const resp = await client.chat.completions.create({
  model: "gpt-5.5",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(resp.choices[0].message.content);
```

**Python (anthropic SDK, pinned to 0.116).**
```python
from anthropic import Anthropic

client = Anthropic(
    base_url="https://api.compute.finance",
    api_key="ct_live_...",
)

resp = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.content[0].text)
```

**TypeScript (@anthropic-ai/sdk, pinned to ^0.36.3).**
```ts
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  baseURL: "https://api.compute.finance",
  apiKey: process.env.COMPUTE_FINANCE_API_KEY!, // ct_live_...
});

const resp = await client.messages.create({
  model: "claude-opus-4-1",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello" }],
});
console.log(resp.content[0].text);
```

**cURL.**
```bash
curl https://api.compute.finance/v1/chat/completions \
  -H "Authorization: Bearer $COMPUTE_FINANCE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-5.5","messages":[{"role":"user","content":"Hello"}]}'
```

---

## Compute Finance ID

Your Compute Finance ID (CF ID) is your identity across all Compute Finance surfaces. Created on first sign-in via email or wallet, it ties together your profile, points balance, and referral code into a single record.

### What CF ID stores

| Field | Description |
|---|---|
| `cf_id` | Public identifier -- format: cf_usr_XXXXXXXXXXXX |
| `email` | Used for notifications. Optional for wallet-only sign-in. |
| `wallet_address` | On-chain address on Base. Created via account abstraction or connected externally. |
| `display_name` | User-chosen name. Defaults to a truncated email or wallet address. |
| `referral_code` | Permanent 8-character code -- format: cf_ref_XXXXXXXX |
| `points_balance` | Current points total, denormalized from the points ledger |

### Sign-in flows

Two sign-in methods, both produce a CF ID:

- **Email** -- Enter your email, receive a 6-digit code, verify. A smart wallet is created on Base and associated with your email. No seed phrase required.
- **Wallet** -- Connect MetaMask, Coinbase Wallet, or any WalletConnect-compatible wallet. Sign a SIWE message. Your wallet address becomes your CF ID's primary identifier.

Both flows converge on the same CF ID record. You can add an email to a wallet-only account later from your settings.

---

## Points

Points track your engagement with Compute Finance -- signup, daily logins, oracle interactions, and referrals. As your balance grows, you unlock higher tiers. Points are append-only and recorded in a public ledger per CF ID.

### Tiers

| Tier | Min Points |
|---|---|
| Explorer | 0 |
| Starter | 500 |
| Builder | 2,000 |
| Architect | 5,000 |
| Titan | 15,000 |

### How points are earned

V1 supports six earning channels. New channels will be added in future versions and announced via the changelog.

| Channel | Amount | Trigger | Frequency |
|---|---|---|---|
| Signup bonus | 100 pts | CF ID created | Once per account |
| Referral (referrer) | 250 pts | Referred user completes signup | Per successful referral |
| Referral (referred user) | 50 pts | User signs up via referral link | Once per account |
| Daily login | 10 pts | User logs in on a new calendar day (UTC) | Once per day |
| 7-day login streak bonus | 50 pts | User logs in 7 consecutive days | Once per streak completion |
| Oracle interaction | 5 pts | User views a unique model's pricing on the oracle page | Up to 12 per day (one per model) |

### Ledger model

The points ledger is an append-only log. No entries are ever updated or deleted. Your canonical points balance is the sum of all your ledger entries. The denormalized `points_balance` field on your CF ID record is a performance optimization that is reconciled periodically.

| Field | Type | Description |
|---|---|---|
| `id` | UUID | Primary key |
| `cf_id` | String (FK) | The user who earned the points |
| `type` | Enum | One of: `signup`, `referral`, `referral_welcome`, `daily_login`, `streak_bonus`, `oracle_interaction` |
| `amount` | Integer | Points earned (always positive -- append-only, no negative entries) |
| `source` | String | Human-readable source descriptor (e.g. `referral:cf_usr_a3k9m2x7p1b4`, `oracle:gpt-5.5`) |
| `created_at` | Timestamp | When the points were earned |

The append-only design means: no points can be silently removed or altered, the complete earning history is preserved and queryable, and any future audit can reconstruct the exact points balance at any point in time.

### Streaks

Use Compute Finance on consecutive calendar days to build a streak. Longer streaks earn bonus points. Your current streak and longest streak are shown in your profile. Streaks reset if you miss a calendar day (UTC).

### Leaderboard

The top 50 users by total points are displayed on the public leaderboard, refreshed periodically. The leaderboard shows display name and points only -- no other profile data is exposed.

### Non-transferability

Points are non-transferable in V1. They have no monetary value, are not convertible to any token or currency, and cannot be sold, traded, or assigned to another account. A points-to-credits conversion ratio for V2 will be announced before V2 ships, and the append-only ledger ensures all V1 earning history is preserved and can be converted accurately at that time.

### API endpoints

Points data is queryable via the following endpoints. Authentication is required for endpoints that return personal data; the leaderboard is public.

Paths are against `https://api.compute.finance`.

| Method | Path | Description |
|---|---|---|
| GET | `/v1/points` | Your points summary (total, tier, current streak, longest streak) |
| GET | `/v1/points/history` | Paginated points ledger entries for your CF ID |
| GET | `/v1/points/leaderboard` | Top 50 users by total points (public, no auth) |

---

## Referral Program

Every CF ID includes a unique referral code (8 characters). Share your link to invite new users -- both sides earn points. The program uses first-touch attribution with a 30-day cookie window.

### Referral rewards

| Event | Points | Who Earns |
|---|---|---|
| New user signs up with your code | 50 pts | New user (welcome bonus) |
| You referred a new user | 250 pts | Referrer |

### Sharing your referral link

Referral URLs have the path `/r/{ref}` on `https://compute.finance`, where `{ref}` is your `cf_ref_*` code.

Find your referral code in your Compute Finance ID settings. Share buttons are available for X, LinkedIn, Telegram, and copy-to-clipboard. The link uses a 30-day attribution cookie -- referrals count when the referred user creates a CF ID within 30 days of clicking your link.

### Attribution model

Referral attribution is first-touch with a 30-day window. The first referral link a user clicks is the one credited if they sign up within the window. Subsequent referral links from other users do not overwrite the original cookie.

How it works step by step:

1. A user visits the referral link (`/r/{ref}` on `https://compute.finance`)
2. The server redirects to `https://compute.finance` and sets a cookie: `cf_ref={ref}` with `Max-Age=2592000` (30 days), `SameSite=Lax`, `Secure`
3. The click is recorded in the database with the referral code, timestamp, hashed IP address, and user agent
4. If the user signs up within 30 days -- even if they navigate directly to `https://compute.finance` without the referral link -- the cookie is read during CF ID creation and the referral relationship is stored
5. If the user has already clicked a different referral link, the first-touch cookie is preserved

### Anti-gaming rules

The referral program enforces several rules to prevent farming and abuse. None of these rules surface error messages -- invalid referrals are silently ignored to avoid leaking information about user accounts.

| Rule | Implementation |
|---|---|
| No self-referral | If the `cf_ref` cookie matches the signing-up user's own referral code, the referral is silently ignored |
| Email deduplication | One CF ID per email -- a user cannot create multiple accounts with the same email to farm referral points |
| IP rate limiting | Maximum 10 CF ID creations per IP address per 24 hours, preventing mass account creation from a single source |
| Click rate limiting | Maximum 100 clicks per referral code per hour. Clicks beyond the limit are not recorded. |
| Disposable email detection | Optional: reject signups from known disposable email domains (mailinator, guerrillamail, etc.) |

### Referral dashboard

Your CF ID profile includes a referral dashboard showing:

- Total referral link clicks (all-time)
- Total signups from your referral link
- Conversion rate (signups / clicks)
- Total points earned from referrals
- List of referred users (display name or truncated email, signup date, status: pending or confirmed)

### Status transitions

A referral has two possible states. Points are awarded when the status transitions from `pending` to `confirmed`:

- **pending** -- The user clicked the referral link but has not yet completed signup
- **confirmed** -- The user has created a CF ID. Points are awarded to both sides within 60 seconds of confirmation.

---

[Disclaimer](https://compute.finance/disclaimer) | [Terms](https://compute.finance/terms) | [Privacy](https://compute.finance/privacy) | [Cookies](https://compute.finance/cookies)

[X](https://x.com/computefin) | [LinkedIn](https://linkedin.com/company/compute-finance)
