Update a Forward Schedule.
POST /api/v1/forward/schedules/{schedule_id}
Uses merge-patch semantics. Fields present in the request are updated; omitted fields remain unchanged.
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <PAT or SAT> |
Content-Type | Yes | application/json |
Idempotency-Key | No | Optional idempotency key for unsafe requests. |
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
schedule_id | string | Yes | Forward Schedule ID. |
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | New Schedule name. |
description | string | No | New Schedule description. |
template_id | string | No | New Forward Template ID. |
initial_events | array | No | Replaces the initial event list. |
execution | object | No | Merge updates the execution policy. |
trigger_policy | object|null | No | Updates the trigger policy. null changes it to manual. |
environment_id | string | No | New execution environment. |
sinks | array|null | No | Omission preserves the current Sink; null or [] clears it; one Pairing Sink replaces it. |
metadata | object | No | Merge updates metadata. null values delete metadata keys. |
Trigger policy
trigger_policy is a typed object. Create and update requests accept only configuration fields: type, expression, and timezone. Passing null changes the Schedule to {"type":"manual"}. upcoming_runs_at and last_run_at are response-only fields computed by Forward.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | cron, once, interval, or manual. |
expression | string | Conditional | Trigger expression. Required for cron, once, and interval; not needed for manual. |
timezone | string | Conditional | IANA timezone, such as Asia/Shanghai. Required for cron; required for once only when expression has no offset; optional for interval and manual. |
upcoming_runs_at | array | Response only | Upcoming trigger times in UTC ISO 8601. The current implementation returns [] or the next scheduled time only. |
last_run_at | string|null | Response only | Most recent trigger time. |
type | Required input | Description |
|---|---|---|
cron | type, expression, timezone | Repeats by a 5-field cron expression in the given IANA timezone. |
once | type, expression, optional timezone | Runs once at an ISO 8601 time. timezone is required when the expression has no offset. |
interval | type, expression | Repeats by an ISO 8601 duration, such as PT15M. |
manual | type | Never runs automatically. Trigger with the Run Schedule endpoint. |
type | expression format | Example | Notes |
|---|---|---|---|
cron | Standard 5-field cron | 0 9 * * * | Minute-level calendar schedule. Seconds and 6-field cron are not supported. |
once | ISO 8601 absolute time | 2026-06-23T09:00:00 or 2026-06-23T01:00:00Z | Runs once. The target time must be at least one minute in the future. |
interval | ISO 8601 duration | PT15M, PT1H, P1D | Fixed interval schedule. Minimum interval is one minute. |
manual | Omitted or empty | - | Does not create scheduled runs. |
Execution policy
execution is merge-updated. Omitted fields keep their current values.
| Field | Type | Default | Description |
|---|---|---|---|
session_mode | string | new_session | new_session or reuse_session. |
max_concurrent_runs | integer | 1 | Maximum concurrent runs for this Schedule. |
max_attempts | integer | 1 | Maximum actual attempts per Run. Allowed values: 1 or 2; values outside this range are rejected. |
timeout_ms | integer | 300000 | Timeout for one attempt. |
session_mode | Description |
|---|---|
new_session | Creates a new execution Session for each trigger. Previous context is not reused. |
reuse_session | Forward manages one fixed execution Session for this Schedule and reuses it across triggers. Callers cannot provide an arbitrary existing session_id. |
max_attempts=2 means the server may automatically retry once after the first execution fails. Whether a retry actually happens depends on the failure type — parameter errors, permission errors, concurrency limits, timeouts, or connection interruptions are not guaranteed to be retried. Clients can check the attempt field on a Schedule Run to see how many attempts were made.
Omitting execution, passing execution=null, passing an empty object, or passing a partial execution without max_attempts all preserve the current max_attempts value. Explicitly passing execution.max_attempts=null is treated as a type error and does not reset to default.
Update the IM sink
A non-empty sinks array may contain only one Pairing Sink, with only type=im_channel and channel_pairing_id:
| Request shape | Result |
|---|---|
sinks omitted | Preserves the current Sink without resolving the Pairing again. |
"sinks": null or "sinks": [] | Clears the Sink and returns []. |
| One valid Pairing Sink | Replaces the complete Sink and returns its normalized form. |
channel_id, channel_type, an external channel user, Conversation, or other raw routing fields. The Pairing must belong to the current user, be active, and match the Schedule Identity and final Template. If template_id is changed while the existing Sink is a Pairing Sink, the request must also clear the Sink or replace it with one matching the new Template. Legacy Tool Sinks retain their compatibility behavior.
Example request
Example response
HTTP 200 OK
Response fields
Returns the updated Schedule object.
Errors
| HTTP | Type | Code | Trigger |
|---|---|---|---|
| 400 | invalid_request_error | invalid_trigger_policy | Trigger policy is invalid. |
| 400 | invalid_request_error | invalid_request | execution.max_attempts is not in the 1..2 range. |
| 400 | invalid_request_error | unsupported_sinks_input | Request body contains sinks. |
| 404 | not_found_error | schedule_not_found | Schedule does not exist. |
| 409 | invalid_request_error | schedule_archived | Schedule is archived. |
| 401 | authentication_error | authentication_required | The PAT or SAT is invalid or expired. |
Notes
- HTTP update requests do not support updating
sinks. reuse_sessionmeans Forward manages a fixed execution Session for this Schedule; callers cannot provide an arbitrary existingsession_id.