> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a schedule

> 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>`                                |
| `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.                                  |
| `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             | Reserved. Current implementation records and validates it but runs once. |
| `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`. |

## Example request

```bash theme={null}
curl -s -X POST 'https://api.qoder.com/api/v1/forward/schedules/sched_019f00112233445566778899aabbccdd' \
  -H "Authorization: Bearer $QODER_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekday tech brief",
    "trigger_policy": {
      "type": "cron",
      "expression": "0 9 * * 1-5",
      "timezone": "Asia/Shanghai"
    }
  }'
```

## Example response

**HTTP 200 OK**

```json theme={null}
{
  "id": "sched_019f00112233445566778899aabbccdd",
  "identity_id": "idn_019eabc123",
  "template_id": "tmpl_support",
  "name": "Weekday tech brief",
  "description": "Generate a daily technology news summary",
  "status": "active",
  "paused_reason": null,
  "initial_events": [
    {
      "type": "user.message",
      "content": "Summarize current technology news in five bullet points."
    }
  ],
  "execution": {
    "session_mode": "new_session",
    "max_concurrent_runs": 1,
    "max_attempts": 1,
    "timeout_ms": 300000
  },
  "trigger_policy": {
    "type": "cron",
    "expression": "0 9 * * 1-5",
    "timezone": "Asia/Shanghai",
    "upcoming_runs_at": ["2026-06-23T01:00:00Z"]
  },
  "environment_id": "env_019e64e01a137caf953ac2ac7b42ec5c",
  "sinks": [],
  "metadata": {},
  "archived_at": null,
  "created_at": "2026-06-22T10:00:00Z",
  "updated_at": "2026-06-22T10:30:00Z"
}
```

## 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` | `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.          |

## Notes

* HTTP update requests do not support updating `sinks`.
* `reuse_session` means Forward manages a fixed execution Session for this Schedule; callers cannot provide an arbitrary existing `session_id`.

## Related

<CardGroup cols={2}>
  <Card title="Get a schedule" icon="file-lines" href="/cloud-agents/api/forward/schedules/get" />

  <Card title="Pause a schedule" icon="pause" href="/cloud-agents/api/forward/schedules/pause" />
</CardGroup>
