---
title: "Update Paper Deployment"
method: POST
path: "/v1/paper/{deployment_id}/update"
tags: ["paper"]
---

# Update Paper Deployment

`POST /v1/paper/{deployment_id}/update`

## Request

- Base URL: `https://api.usekeel.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.usekeel.io/v1/paper/{deployment_id}/update`
- Auth: none declared

Move a LIVE or PAUSED paper run onto the strategy's head (S01 §3.13).

The twin of ``update_live``: the same coordination marker
(``UPDATE_PENDING`` / ``UPDATE_FAILED`` / ``UPDATE``), the same PAUSED
barrier with the Scheduler change behind it, and the same artifact gates
(equivalence, validity, known issues, flow-series grade, serving with no
account), without the account-mode gate and without operator blocks.
The completing transaction restores the original status, binds a fresh
config from the ONE builder through ``deployments.config_id`` (never
``strategies.active_config_id``, PT2-45), sets ``last_viewed_at`` (an
update is a visit) and writes the ``UPDATE`` row and
``UPDATE_COMPLETED`` with the new commit; after commit
``on_paper_update_completed`` fires once. A retry completes a pending
update rather than starting a new one.

The label and the marker (SOAK-S2): the run is relabelled ``v{N}`` by the
target commit's sequence, as the create labels it, and NO release tag is
minted (live's ``_reserve_live_update_release`` is not called): a paper
move is not a release, and a reserved ``release-vN.0`` shifted the
strategy's live version sequence. The marker's ``version_string`` is the
paper-owned key :func:`_paper_update_coordination_key`, unique per update
on the run, so live's resolver (unchanged) still pairs each pending
update with its own ``UPDATE`` event.

## Path parameters

- `deployment_id` string, required

## Headers

- `Authorization` string, nullable
- `X-Org-Id` string, nullable

## Request body

- PaperUpdateRequest: ``POST /v1/paper/{id}/update`` (S01 §3.13). Unknown keys are refused (422). The paper twin of ``UpdateLiveRequest`` without its operator blocks: a paper run carries no tranching and no maker style, so the one option is the cron spelling, which must equal the selected commit's derived schedule.
  - `schedule` string, nullable: Optional cron spelling; it must equal the selected commit's derived schedule.

## Response `200`

Successful Response

- DeploymentResponse
  - `deployment_id` string, required
  - `strategy_id` string, required
  - `name` string, required
  - `status` string, required
  - `schedule` string, nullable
  - `evaluation_grid` EvaluationGrid: The candle closes a deployment's runs evaluate (UX-8). Closes sit at ``offset_minutes`` past 00:00 UTC and every ``period_minutes`` after it: the deployment's cron inverted under its persisted dispatch generation (``utils.schedule.evaluation_grid``), so a pre-arm cron that fires at 11:59 reads as the 12:00 close it evaluates.
    - `period_minutes` integer, required
    - `offset_minutes` integer, required
  - `source_hash` string, nullable
  - `s3_key` string, nullable
  - `org_id` string, nullable
  - `account_id` string, nullable
  - `deployed_at` string, nullable
  - `stopped_at` string, nullable
  - `created_at` string, nullable
  - `updated_at` string, nullable
  - `deployed_commit_id` string, nullable
  - `deployed_version_string` string, nullable
  - `config_id` string, nullable
  - `total_pnl` number, nullable
  - `position_count` integer, nullable
  - `venue` VenueBlock: Which venue a deployment or account runs on, and its money class. Paper Trading v2, S01 §3.10 / IC-01-9. ``capital_class`` is ``trading.accounts.capital_class`` (``real`` or ``practice``); ``code`` is the venue's ``trading.venues.code`` (``HL``, ``PAPER``). On a deployment whose ``account_id`` names no account row (no foreign key refuses one, ``V6.0__deployments.sql:16``) the block reads ``{code: null, capital_class: "real"}``: such a row predates paper and keeps its pre-paper meaning. Clients key on this block, never on a probe.
    - `code` string, nullable
    - `capital_class` string, required
  - `remaining` object, nullable
  - `universe_warnings` UniverseWarning[], nullable
    - `symbol` string, required
    - `reason` 'DELISTED' | 'STALE', required
    - `detail` string, required
  - `account_warnings` AccountWarning[], nullable
    - `kind` 'EQUITY_BELOW_VENUE_MINIMUM' | 'ORDERS_SKIPPED_MIN_NOTIONAL' | 'EXITS_BELOW_VENUE_MINIMUM' | 'POSITION_STRANDED_BELOW_MINIMUM', required
    - `account_value` number, required
    - `min_notional` number, required
    - `detail` string, required
    - `orders_skipped` integer, nullable
    - `orders_total` integer, nullable
    - `exits_skipped` integer, nullable
    - `window_days` integer, nullable
    - `exit_symbols` string[], nullable
  - `execution_style` 'market' | 'maker', nullable
  - `paused_reason` string, nullable
  - `paused_at` string, nullable
  - `tranching` object, nullable
  - `health` 'running' | 'degraded' | 'stalled' | 'stopped', nullable
  - `health_detail` HealthDetailResponse: IC-04-2's ``health_detail`` (S04 §3.10.2): the first predicate that matched, the count of most recent consecutive missing bars, the newest COMPLETE bar, and the bar label the current state began at.
    - `reason` 'consecutive_missing' | 'latest_eval_failed' | 'latest_execution_failed' | 'dispatch_exhausted' | 'execution_missing' | 'rail_blocked' | 'funding_stalled' | 'equity_stale' | 'failure_rate' | 'silence' | 'halted' | 'schedule_unreadable', nullable, required
    - `consecutive_missing` integer, required
    - `last_complete_at` string, date-time, nullable, required
    - `since` string, date-time, nullable, required
  - `parity` ParityBlock: IC-03-2: the record's latest non-day-0 snapshot, else its first day-0 row.
    - `residual_bps` number, nullable, required
    - `status` 'tracking' | 'drifting' | 'under_review', required
    - `window_start` string, date-time, nullable, required
    - `window_end` string, date-time, nullable, required
    - `as_of` string, date-time, nullable, required
    - `eval_count` integer, required
    - `meter_eligible` boolean, required
    - `day0_backtest_run_id` string, nullable, required
    - `is_day0` boolean, required
    - `paper_return_pct` number, nullable, required
    - `backtest_return_pct` number, nullable, required
  - `graduation` GraduationBlock: IC-03-5: the graduation criteria state, computed on read. ``record`` and ``carry_over`` are null only for a deployment with no deployed commit (the record has no commit to name).
    - `ready` boolean, required
    - `ready_since` string, date-time, nullable, required
    - `nudged_at` string, date-time, nullable, required
    - `evaluated_at` string, date-time, required
    - `record` GraduationRecord, required: IC-03-5 ``record``: the record the criteria run over (R-27).
      - `started_at` string, date-time, required
      - `commit_id` string, required
      - `commit_seq` integer, required
      - `commit_changed_at` string, date-time, nullable, required
    - `thresholds` GraduationThresholds, required: IC-03-5 ``thresholds``: frozen at create from the defaults version (IC-03-6).
      - `min_age_days` integer, required
      - `min_evals` integer, required
      - `parity_band_bps` number, required
      - `backtest_max_dd_pct` number, nullable, required
      - `dd_floor_pending` boolean, required
      - `defaults_version` integer, required
    - `criteria` GraduationCriteria, required
      - `age` AgeCriterion, required
        - `met` boolean, required
        - `days` integer, required
        - `required_days` integer, required
      - `evals` EvalsCriterion, required
        - `met` boolean, required
        - `count` integer, required
        - `required` integer, required
      - `parity` ParityCriterion, required
        - `met` boolean, required
        - `residual_bps` number, nullable, required
        - `band_bps` number, required
        - `as_of` string, date-time, nullable, required
        - `eval_count` integer, required
        - `meter_eligible` boolean, required
        - `stale` boolean, required
      - `drawdown` DrawdownCriterion, required: Both drawdowns are positive magnitudes; the floor is null while pending.
        - `met` boolean, required
        - `paper_max_dd_pct` number, nullable, required
        - `backtest_max_dd_pct` number, nullable, required
    - `carry_over` CarryOver, required: IC-03-5 ``carry_over`` (S03 §3.9.5, R-32): no simulated capital.
      - `strategy_id` string, required
      - `commit_id` string, required
      - `schedule` string, nullable, required
      - `source_paper_deployment_id` string, required
      - `head_commit_id` string, required
      - `commit_ahead` boolean, required
      - `commit_seq` integer, required
      - `head_commit_seq` integer, required
      - `simulated_capital` string, nullable
      - `min_order_notional` string, nullable
  - `money_freshness` MoneyFreshness: Coverage state of the money facts behind a performance read (spec 04 §5.1, M4). Freshness is part of the answer: the number beside this block is only as fresh as the capture coverage that produced its inputs, and this block says exactly how fresh — * ``COVERED`` — coverage reaches the requested interval's end; ``fresh_as_of`` is the weakest fact class's reach. * ``SYNCING`` — the interval is managed and post-epoch but coverage has not reached its end yet; ``synced_through`` is how far it has (null when no coverage row speaks for the interval at all — absence never reads as fresh). * ``LEGACY`` — the interval predates the account's first coverage row (the epoch cutover): pre-capture history, served ungated but labeled. Until the capture lane goes live, every account reads this. * ``UNMANAGED`` — the interval overlaps no managed window; strategy performance is not defined there. Phase 1 labels only — no numeric field elsewhere in the response changes because of this block.
    - `state` 'COVERED' | 'SYNCING' | 'LEGACY' | 'UNMANAGED', required
    - `fresh_as_of` string, nullable
    - `synced_through` string, nullable
  - `serving_warnings` object[], nullable
  - `known_issues` KnownIssueRef[], nullable
    - `id` string, required
    - `summary` string, required
  - `live_window_warnings` LiveWindowWarning[], nullable
    - `code` 'LIVE_WINDOW_SHORTER_THAN_TRADES', required
    - `message` string, required
    - `backtest_run_id` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/usekeel/apis/keel-api.md) · [All operations](https://skmtc.dev/usekeel/apis/keel-api/llms.txt) · [OpenAPI document](https://skmtc.dev/usekeel/apis/keel-api/revisions/3191ca10b0ab?raw)
