---
title: "Preview a spend rule"
method: GET
path: "/spend-rules/{id}/preview"
tags: ["Gateway"]
---

# Preview a spend rule

`GET /spend-rules/{id}/preview`

## Request

- Base URL: `https://api.phaseo.app/v1`
- URL: `https://api.phaseo.app/v1/spend-rules/{id}/preview`
- Auth: HTTP bearer

Returns the rule's current period, spend so far, base, percent and next threshold, computed as the evaluator computes them, without sending or recording anything.

## Response `200`

Spend rule preview

- SpendRulePreviewResponse
  - `data` SpendRulePreview, required: Where a spend rule stands now. Rolling rules have their window as period. Forecast rules have a forecast object, and their thresholds are measured against the projection. Balance rules have the burn-rate window as period, the available balance as value and a balance object. Spike rules have their window as period, the spend over it as value, the median of the same window over the previous 7 days as base, the point they fire at as next_threshold and a spike object.
    - `rule_id` string, uuid, required
    - `metric` 'spend' | 'budget_percent' | 'forecast' | 'spike' | 'balance', required: spend: spend reached threshold_amount. budget_percent: spend reached threshold_percents of the base. forecast: spend projected to the period end reaches the threshold. spike: spend over the last window_hours is at least spike_multiplier times the median of the same window over the previous 7 days, and at least spike_floor. balance: the workspace balance or runway falls below the threshold.
    - `evaluated` boolean, required: Whether the evaluator handles the rule's metric, period and base. Every rule the API accepts is evaluated.
    - `computed_at` string, date-time, required
    - `time_zone` string, required
    - `period` object, nullable, required
      - `kind` 'day' | 'week' | 'month' | 'rolling', required: day, week (from Monday) or month in the rule's time zone, or rolling over the last window_hours.
      - `start` string, date-time, required
      - `end` string, date-time, required
      - `window_hours` integer: Rolling rules only: the window length in hours.
    - `value_nanos` integer, nullable, required
    - `value_usd` number, nullable, required
    - `base_kind` 'amount' | 'workspace_budget' | 'key_limit' | 'previous_period', nullable, required
    - `base_ref` 'daily' | 'weekly' | 'monthly', nullable, required
    - `base_nanos` integer, nullable, required
    - `base_usd` number, nullable, required
    - `previous_period` object, nullable, required: previous_period bases only: the stretch of the previous period the base covers (the same point in the previous period, the window before a rolling one, or the whole previous period for a forecast). Null for other bases.
      - `start` string, date-time, required
      - `end` string, date-time, required
    - `forecast` object, nullable, required: Forecast rules only: spend at the period end if the pace so far continues (a straight line from the period start, as the usage dashboard projects). Null for other rules.
      - `ready` boolean, required: False until enough of the period has passed to project: 3 hours of a day, 24 hours of a week or 72 hours of a month.
      - `from` string, date-time, nullable, required: When the projection starts.
      - `projected_nanos` integer, nullable, required
      - `projected_usd` number, nullable, required
      - `projected_percent` number, nullable, required: The projection as a percent of the base.
      - `by` string, date-time, required: The period end the projection is for.
      - `limit_nanos` integer, nullable, required: What the forecast is measured against: the amount threshold, else the base.
      - `limit_usd` number, nullable, required
      - `reaches_at` string, date-time, nullable, required: When the pace so far reaches the limit, if it does before the period ends.
    - `percent` number, nullable, required
    - `threshold_percents` integer[], nullable, required
    - `threshold_amount_nanos` integer, nullable, required
    - `threshold_amount_usd` number, nullable, required
    - `reached_threshold_percent` integer, nullable, required
    - `next_threshold` object, nullable, required: The next threshold the value has not reached: a percent of the base (null for amount thresholds) and its amount.
      - `percent` integer, nullable, required
      - `amount_nanos` integer, required
      - `amount_usd` number, required
    - `block_at_nanos` integer, nullable, required
    - `block_at_usd` number, nullable, required
    - `state` object, nullable, required
      - `highest_percent_fired` integer, nullable, required
      - `amount_fired_at` string, date-time, nullable, required
      - `last_fired_at` string, date-time, nullable, required
      - `fire_count` integer, required
      - `armed` boolean: Balance rules: false after an alert until the balance is back above the threshold.
    - `balance` object, nullable, required: Balance rules only: where the balance stands, as the evaluator sees it. Null for other rules.
      - `balance_usd` number, required
      - `reserved_usd` number, required
      - `available_nanos` integer, required: Balance minus reserved credit: what requests are admitted against.
      - `available_usd` number, required
      - `window_hours` integer, required
      - `burn_usd` number, required
      - `burn_per_day_usd` number, required
      - `runway_days_left` number, nullable, required: Days the available balance lasts at the burn rate. Null without spend in the window.
      - `low_balance` boolean, required
      - `low_runway` boolean, required
      - `armed` boolean, required
      - `auto_top_up_covers` boolean, required: Auto Top-Up is on and working, so a drop is recorded without an alert.
    - `spike` object, nullable, required: Spike rules only: spend over the last window_hours against the median of the same window over the previous 7 days, as the evaluator sees it. Null for other rules.
      - `window_hours` integer, required
      - `current_nanos` integer, required
      - `current_usd` number, required
      - `baseline_nanos` integer, required: The median of the same window over the previous 7 days: the same hours on each of the 7 days before for windows under 24 hours, else the non-overlapping windows before it that fit in 7 days.
      - `baseline_usd` number, required
      - `multiple` number, nullable, required: Spend over the window divided by the baseline. Null when the baseline is 0, when only the floor applies.
      - `multiplier` number, required
      - `floor_usd` number, required
      - `fires_at_nanos` integer, required: What spend over the window must reach to fire: the larger of spike_multiplier times the baseline and the floor.
      - `fires_at_usd` number, required
      - `baseline_windows` integer, required: How many windows the baseline has. A rule needs at least 3.
      - `active_windows` integer, required: Baseline windows in which the workspace spent anything.
      - `history_ready` boolean, required: False until the workspace has spent in at least 3 baseline windows. The rule does not fire before then.
      - `spiking` boolean, required: Whether the rule would fire now, before the cooldown.
      - `cooldown_until` string, date-time, nullable, required: When the cooldown after the last alert ends, if it has not yet.
    - `alert` object, nullable, required: The text an alert would carry now, naming the highest threshold reached, or the first.
      - `scope_label` string, required
      - `title` string, required
      - `message` string, required

## Other responses

- `default`: Request failed

## Changes

- **2026-10-30** `56f46b5b6b41`: 1 info
  - added the required property `data/spike` to the response with the `200` status
- **2026-10-29** `4d6438af4709`: 3 info
  - added the optional property `data/period/window_hours` to the response with the `200` status
  - added the required property `data/forecast` to the response with the `200` status
  - added the required property `data/previous_period` to the response with the `200` status
- **2026-10-29** `9b2f62a69f66`: 2 info
  - added the optional property `data/state/armed` to the response with the `200` status
  - added the required property `data/balance` to the response with the `200` status
- **2026-10-27** `58847d40a023`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/phaseo/apis/phaseo-gateway-api/changes/spend-rules/:id/preview/get.md)

---

[API](https://skmtc.dev/phaseo/apis/phaseo-gateway-api.md) - [All operations](https://skmtc.dev/phaseo/apis/phaseo-gateway-api/llms.txt) - [OpenAPI document](https://skmtc.dev/phaseo/apis/phaseo-gateway-api/revisions/5ca9bb220d25?raw)
