---
title: "Upsert Workflow Play Schedule"
method: POST
path: "/api/plays/{play_id}/schedules"
tags: ["plays"]
---

# Upsert Workflow Play Schedule

`POST /api/plays/{play_id}/schedules`

## Request

- Base URL: `https://platform.verbiflow.com/api/bridge`
- URL: `https://platform.verbiflow.com/api/bridge/api/plays/{play_id}/schedules`
- Auth: one of:
  - HTTP bearer and API key in header `x-flage-org-id`
  - HTTP bearer and API key in header `x-flage-org-slug`

## Path parameters

- `play_id` string, required

## Request body

- WorkflowPlayScheduleRequest: Create or replace a schedule definition for an existing immutable Play revision.
  - `delivery_target` WorkflowPlayScheduleDeliveryTargetRequest: Slack workspace and channel selected for proactive schedule delivery.
    - `channel_id` string, required: Exact Slack channel id for proactive delivery.
    - `kind` 'slack_channel', required: Delivery target discriminator; only Slack channel is supported.
    - `team_id` string, required: Exact connected Slack workspace id.
  - `expected_revision_id` string, nullable: Optional ready code revision compare-and-set guard for schedule definition and authority changes.
  - `expected_updated_at` string, date-time, nullable: Exact updated_at timestamp from plays.schedules.get. The server rejects a stale edit instead of overwriting another operator's changes.
  - `metadata` object: Caller-owned schedule metadata plus server-authored provenance fields.
  - `next_run_at` string, date-time, nullable: Optional first due time for interval or once schedules as an ISO timestamp with timezone offset. Calendar schedules derive it and use schedule_spec.starts_at as the optional lower bound.
  - `run_template` object: Revision-defined occurrence input. Keys and values must match the active Play input schema; thread_id is reserved because every tick gets a fresh execution context.
  - `schedule_slug` string, nullable: Stable human-readable schedule key for idempotent upsert, for example daily-review. Keep it stable when editing the same schedule.
  - `schedule_spec` union, required: Timing rule for a Play schedule. Interval schedules repeat after a duration; calendar schedules run at a local wall-clock time; once schedules run once; manual schedules run only through run-now or admitted events.
    - union
      - object
        - `cadence_seconds` integer, required: Seconds between occurrences. This is the canonical interval field.
        - `interval_seconds` integer: Legacy alias for cadence_seconds retained for existing schedules.
        - `type` 'interval': Selects duration-based recurrence.
      - object
        - `cadence_seconds` integer: Seconds between occurrences. This is the canonical interval field.
        - `interval_seconds` integer, required: Legacy alias for cadence_seconds retained for existing schedules.
        - `type` 'interval': Selects duration-based recurrence.
    - object
      - `at` string, date-time: Timezone-aware occurrence time. next_run_at may supply it instead.
      - `type` 'once', required: Selects a single occurrence.
    - object
      - `type` 'manual', required: Disables time-driven occurrences while allowing manual and event admission.
  - `status` 'enabled' | 'disabled': Initial schedule status. Direct HTTP requests default to enabled; the Python SDK sends disabled by default to allow review before activation.

## Response `200`

Successful Response

- WorkflowPlayScheduleResponse: Envelope returned by single-schedule operations.
  - `schedule` WorkflowPlayScheduleRecord, required: Durable schedule definition, authority fence, and health projection.
    - `active_code_revision_id` string, nullable, required: Immutable revision pinned when admitting new ticks.
    - `authority_grant_version` integer, required: Monotonic authority version used to fence schedule edits and ticks.
    - `authority_status` 'unconfigured' | 'active' | 'needs_reauthorization' | 'revoked', required: State of the durable member authority used to execute new ticks.
    - `created_at` string, required: ISO 8601 schedule creation time.
    - `delivery_target` WorkflowPlayScheduleDeliveryTarget, required: Slack destination snapshotted into a schedule and each admitted tick.
      - `app_id` string, nullable: Slack app id resolved when the destination was validated.
      - `channel_id` string, required: Slack channel id that receives completion notifications.
      - `installation_id` string, nullable: Workspace installation id resolved when the destination was validated.
      - `kind` 'slack_channel', required: Selects Slack channel delivery.
      - `team_id` string, required: Slack workspace id containing the destination channel.
    - `draft_code_revision_id` string, nullable, required: Latest authored revision available for verification and activation.
    - `enable_requires_successful_manual_tick` boolean, required: True until the activated revision completes one matching manual tick.
    - `health` WorkflowPlayScheduleHealth, required: Operator health projection derived from schedule, authority, and tick state.
      - `attention_required` boolean, required: True when the health state requires operator review or recovery.
      - `changed_at` string, nullable, required: ISO 8601 time when the health classification last changed.
      - `reason` string, nullable, required: Sanitized explanation for the current health state.
      - `status` 'healthy' | 'needs_reauthorization' | 'needs_sync' | 'paused_authority' | 'paused_deterministic' | 'paused_transient' | 'paused_unknown_effect', required: Current health classification used to choose the permitted recovery action.
    - `last_tick_id` string, nullable, required: Most recently admitted tick id.
    - `metadata` object, required: Schedule metadata, including authorship and provider-specific provenance keys.
    - `needs_reauthorization` boolean, required: True when authority_status is not active and new work needs renewed authority.
    - `next_run_at` string, nullable, required: Next computed ISO 8601 occurrence time, or null when no time-driven run is due.
    - `notification_rule_digest` string, nullable, required: Digest of the exact notification rule bound at activation.
    - `notification_rule_id` string, nullable, required: Notification rule bound to completed schedule ticks.
    - `play_id` string, required: Play whose immutable revision this schedule executes.
    - `run_template` object, required: Revision-defined input object passed to each occurrence. Its keys come from the active Play input schema.
    - `run_template_hash` string, required: Digest of the canonical run_template JSON.
    - `schedule_id` string, required: Stable schedule id used by tick and authority records.
    - `schedule_slug` string, required: Stable human-readable name within the Play.
    - `schedule_spec` union, required: Timing rule for a Play schedule. Interval schedules repeat after a duration; calendar schedules run at a local wall-clock time; once schedules run once; manual schedules run only through run-now or admitted events.
      - union
        - object
          - `cadence_seconds` integer, required: Seconds between occurrences. This is the canonical interval field.
          - `interval_seconds` integer: Legacy alias for cadence_seconds retained for existing schedules.
          - `type` 'interval': Selects duration-based recurrence.
        - object
          - `cadence_seconds` integer: Seconds between occurrences. This is the canonical interval field.
          - `interval_seconds` integer, required: Legacy alias for cadence_seconds retained for existing schedules.
          - `type` 'interval': Selects duration-based recurrence.
      - object
        - `at` string, date-time: Timezone-aware occurrence time. next_run_at may supply it instead.
        - `type` 'once', required: Selects a single occurrence.
      - object
        - `type` 'manual', required: Disables time-driven occurrences while allowing manual and event admission.
    - `status` 'enabled' | 'disabled', required: Schedule lifecycle state.
    - `updated_at` string, required: ISO 8601 last schedule mutation time.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/verbiflow/apis/verbiflow-sdk-http-contract.md) - [All operations](https://skmtc.dev/verbiflow/apis/verbiflow-sdk-http-contract/llms.txt) - [OpenAPI document](https://skmtc.dev/verbiflow/apis/verbiflow-sdk-http-contract/revisions/c80e903ef8f3?raw)
