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

# Get Contract Budget

> Read a linked contract's budget: funded milestone volume, consumed work, remaining volume, and the OK / LOW / DEPLETED state.

Returns the contract's current budget: funded milestone volume versus consumed work, and the resulting `OK` / `LOW` / `DEPLETED` state. Read-only and side-effect-free — polling it never emits events. Use it to reconcile after downtime or to render budget status in your UI; the [usage-sync guide](/docs/developers/annotation-platforms/usage-sync) explains how the numbers are computed.

**Requirements:** `contracts:read` scope, and the contract's job must be referenced by a [project link](/docs/developers/annotation-platforms/project-links) on the calling token's install.

## Request

<ParamField path="contractId" type="string" required>
  The OpenTrain contract to read.
</ParamField>

## Response

<ResponseField name="contractId" type="string">
  The contract this budget describes.
</ResponseField>

<ResponseField name="paymentType" type="string | null">
  `PAY_PER_HOUR`, `PAY_PER_LABEL`, or `FIXED_PRICE`. Determines the volume unit (hours, labels) — `FIXED_PRICE` contracts never deplete.
</ResponseField>

<ResponseField name="state" type="string">
  `OK` (below 80% consumed), `LOW` (`consumedFraction` ≥ 0.8), or `DEPLETED` (≥ 1.0). Always `OK` for `FIXED_PRICE` or when nothing is funded.
</ResponseField>

<ResponseField name="fundedVolume" type="number">
  Total volume (hours or labels) across funded and completed milestones.
</ResponseField>

<ResponseField name="fundedAmountUsd" type="number">
  Total USD across those milestones.
</ResponseField>

<ResponseField name="consumed" type="object">
  Raw consumption totals across all reported usage and OpenTrain first-party work: `seconds`, `hours`, `labels`, `tasks`.
</ResponseField>

<ResponseField name="consumedVolume" type="number">
  Consumption in the contract's volume unit — hours for `PAY_PER_HOUR`, labels for `PAY_PER_LABEL`.
</ResponseField>

<ResponseField name="remainingVolume" type="number">
  `fundedVolume - consumedVolume`, floored at 0.
</ResponseField>

<ResponseField name="consumedFraction" type="number">
  `consumedVolume / fundedVolume`, rounded to 4 decimals. `0` when nothing is funded.
</ResponseField>

<ResponseField name="activeMilestone" type="object | null">
  The current funded milestone (`id`, `name`, `amountUsd`, `volume`, `status`), or `null` if none is active.
</ResponseField>

<ResponseField name="lastUsageAt" type="string | null">
  ISO 8601 timestamp of the most recent usage report or first-party work record — `null` if no work has been recorded.
</ResponseField>

## Errors

| Status | `code`         | Meaning                                                      |
| ------ | -------------- | ------------------------------------------------------------ |
| `401`  | `UNAUTHORIZED` | Missing, invalid, or revoked token                           |
| `403`  | `FORBIDDEN`    | Token lacks `contracts:read`                                 |
| `404`  | `NOT_FOUND`    | Contract not found, or its job is not linked by this install |

<RequestExample>
  ```bash curl theme={null}
  curl -sS "https://app.opentrain.ai/api/partner/v1/contracts/<CONTRACT_ID>/budget" \
    -H "Authorization: Bearer $OT_PARTNER_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "contractId": "<CONTRACT_ID>",
    "paymentType": "PAY_PER_HOUR",
    "state": "LOW",
    "fundedVolume": 40,
    "fundedAmountUsd": 560,
    "consumed": { "seconds": 118800, "hours": 33, "labels": 0, "tasks": 87 },
    "consumedVolume": 33,
    "remainingVolume": 7,
    "consumedFraction": 0.825,
    "activeMilestone": {
      "id": "<MILESTONE_ID>",
      "name": "Week 2",
      "amountUsd": 280,
      "volume": 20,
      "status": "ACTIVE_FUNDED"
    },
    "lastUsageAt": "2026-06-12T18:00:00.000Z"
  }
  ```
</ResponseExample>
