---
title: "Append a proposed plan revision"
method: POST
path: "/experiments/{experiment_id}/finetune-plans/propose"
tags: ["finetune-plans"]
---

# Append a proposed plan revision

`POST /experiments/{experiment_id}/finetune-plans/propose`

Record a proposed revision, or apply it when it only narrows.

Proposing grants nothing on its own. The one exception is a revision that
takes authority away: it cannot let the Experiment do anything new, so it
applies immediately. Pressing stop is that same path with no permitted
base model, no training jobs, and every capability off.

Args:
    experiment_id: Experiment the plan belongs to.
    request: Proposed envelope and intent.
    auth: Authenticated caller.

Returns:
    The stored revision.

## Path parameters

- `experiment_id` string, uuid, required

## Request body

- FinetunePlanProposeRequest — Payload for appending a proposed plan revision. Proposing grants nothing. It records what the clarifier and user settled on so the user can read it on a card and decide; only ``approve`` confers authority. ``quote`` is required on any granting propose; the service derives ``estimated_cost_usd`` from it before the digest is taken. A full revoke may omit it so a pre-ENG-6414 plan can be stopped without inventing a basis.
  - `envelope` FinetunePlanEnvelope, required — The machine-checked half of a plan (EDD section 6.1). Every field here maps to a check on a real route. A field that does not belongs in the intent instead -- that split is what keeps "envelope" an enforceable word rather than a decorative one. Note there is no spend limit: owner-set limits are team- and project-scoped only (ENG-6083).
    - `expires_at` string, date-time, required
    - `allow_synthetic_data` boolean
    - `allow_eval_upload` boolean
    - `allowed_base_models` string[]
    - `baseline_model_ids` string[]
    - `allow_preview_deployment` boolean
    - `allow_deployment` boolean
  - `intent` FinetunePlanIntentInput, required — The write shape of intent: everything an approver reads except the quote. ``estimated_cost_usd`` is deliberately absent. The field is derived at propose from ``FinetunePlanQuoteBasis`` and lives only on the response model, so a caller-supplied figure is a 422 rather than a stored value.
    - `objective` string, required
    - `success_criteria` string, nullable
    - `baseline` string, nullable
    - `dataset_reasoning` string, nullable
    - `prose_constraints` string, nullable
    - `extra` object
  - `quote` FinetunePlanQuoteBasisInput — Pricing inputs the server quotes from. Assumptions, not constraints. The stored ``estimated_cost_usd`` is derived from these fields via ``quote_cost_usd``. They are not hashed: they are inputs to a value that already is.
    - `quote_model` string, required
    - `estimated_gpu_minutes` union, required
      - number
      - string
    - `estimated_instance_type` string, required
  - `requires_explicit_approval` boolean

## Response `201`

Successful Response

- FinetunePlanResponse — One plan revision as returned to a user-authenticated caller.
  - `id` string, uuid, required
  - `experiment_id` string, uuid, required
  - `revision` integer, required
  - `revision_hash` string, required
  - `envelope` FinetunePlanEnvelope, required — The machine-checked half of a plan (EDD section 6.1). Every field here maps to a check on a real route. A field that does not belongs in the intent instead -- that split is what keeps "envelope" an enforceable word rather than a decorative one. Note there is no spend limit: owner-set limits are team- and project-scoped only (ENG-6083).
    - `expires_at` string, date-time, required
    - `allow_synthetic_data` boolean
    - `allow_eval_upload` boolean
    - `allowed_base_models` string[]
    - `baseline_model_ids` string[]
    - `allow_preview_deployment` boolean
    - `allow_deployment` boolean
  - `intent` FinetunePlanIntent, required — The recorded, rendered, never-checked half of a plan (EDD section 6.1). ``estimated_cost_usd`` is server-derived at propose (ENG-6414) and shown beside the work so a user can tell a rounding error from a serious bill. Spend is bounded by team and project limits (ENG-6083), not this row.
    - `objective` string, required
    - `success_criteria` string, nullable
    - `baseline` string, nullable
    - `dataset_reasoning` string, nullable
    - `prose_constraints` string, nullable
    - `extra` object
    - `estimated_cost_usd` string, nullable
  - `quote` FinetunePlanQuoteBasisOutput — Pricing inputs the server quotes from. Assumptions, not constraints. The stored ``estimated_cost_usd`` is derived from these fields via ``quote_cost_usd``. They are not hashed: they are inputs to a value that already is.
    - `quote_model` string, required
    - `estimated_gpu_minutes` string, required
    - `estimated_instance_type` string, required
  - `is_current` boolean, required
  - `proposed_by` string, uuid, required
  - `proposed_at` string, date-time, required
  - `approved_by` string, uuid, nullable, required
  - `approved_at` string, date-time, nullable, required
  - `rejected_by` string, uuid, nullable, required
  - `rejected_at` string, date-time, nullable, required

## Other responses

- `422` — Validation Error

## Changes

- **2026-09-24** `1cffaad2a921` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/pioneer/apis/brain-api/changes/experiments/:experiment_id/finetune-plans/propose/post.md)

---

[API](https://skmtc.dev/pioneer/apis/brain-api.md) · [All operations](https://skmtc.dev/pioneer/apis/brain-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pioneer/apis/brain-api/revisions/1cffaad2a921?raw)
