---
title: "Update a routine"
method: PATCH
path: "/api/v1/ai/routines/{id}"
tags: ["AI Routines"]
---

# Update a routine

`PATCH /api/v1/ai/routines/{id}`

Update a routine. All request fields are optional, and only supplied fields are changed. Supplying `destination` replaces the full recipient configuration. Supplying a new `condition` recomposes it and verifies it by default; `null` removes it. Every conditional routine response includes its persisted semantic query; a newly derived condition also includes its verification result.

## Path parameters

- `id` string, uuid, required — The UUID of the routine.

## Query parameters

- `userId` string, uuid — Target user membership ID (for org-scoped API keys)

## Request body

- RoutineUpdateBody
  - `condition` object, nullable — Replaces the delivery condition: Omni recomposes the condition query, verifies it by default, resets the comparison baseline, and cancels any in-flight condition evaluation so a run started under the old condition cannot deliver. Pass null to remove the condition, making the routine deliver on every scheduled run. Omit to leave the stored condition unchanged. Resending the stored condition text unchanged is a no-op.
    - `conditionPrompt` string, required — The delivery condition in plain language. Omni composes a semantic query from this text.
    - `verify` boolean — Whether Omni should run the generated condition query before saving. Defaults to true. Verification confirms that the query runs against the warehouse and establishes the comparison baseline. Set false to save without running the query; the next scheduled evaluation then establishes the baseline for change-based conditions.
  - `description` string, nullable — Display-only notes about the routine. Pass null to clear it.
  - `destination` union
    - object — Replaces the routine's full recipient configuration with the supplied destination.
      - `recipientEmails` string[] — Email addresses that receive each scheduled run of the routine.
      - `type` 'email', required — Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.
      - `userGroupIds` string[] — User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.
    - object — Replaces the routine's full recipient configuration with the supplied destination.
      - `recipientId` string, required — The Slack channel ID (e.g. "C01234567") or user ID (e.g. "U01234567") that receives each scheduled run. Exactly one recipient per Slack routine.
      - `slackRecipientType` 'channel' | 'users', required — Whether `recipientId` is a Slack channel or a user (delivered as a direct message).
      - `type` 'slack', required — Selects Slack delivery — each scheduled run is posted to one Slack channel or sent as a direct message to one user.
  - `name` string — New customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries.
  - `prompt` string — New natural language prompt for the routine: what Omni runs and delivers on each scheduled run.
  - `schedule` string — New six-field cron expression (minute, hour, day-of-month, month, day-of-week, year; use `?` for an unspecified day field). Minimum frequency is once per hour.
  - `timezone` string — New IANA timezone identifier used to evaluate the schedule.

## Response `200`

Updated routine details.

- RoutineUpdateResponse
  - `branchId` string, uuid, nullable, required — Branch of the shared model the prompt runs against, or null.
  - `condition` RoutineConditionUpdateResponse, nullable, required — The saved delivery condition and persisted query, or null for a routine that delivers on every scheduled run. A condition derived by this request also includes its verification result.
    - `conditionPrompt` string, nullable, required — The routine's delivery condition, in plain language. Null for routines created before Omni stored delivery-condition text.
    - `conditionType` 'RESULTS_CHANGED' | 'RESULTS_UNCHANGED' | 'RESULTS_PRESENT' | 'RESULTS_MISSING', required — How Omni evaluates the condition. RESULTS_PRESENT delivers when the condition query returns rows, RESULTS_MISSING when it returns none, RESULTS_CHANGED when its results differ from the previous scheduled run, and RESULTS_UNCHANGED when they are identical.
    - `query` object, required — The persisted semantic query Omni evaluates for this condition. This can be inspected or passed to the query API.
      - `fields` string[], required — Ordered list of fully qualified field names to include in the query (e.g., "view_name.field_name").
      - `filters` object — Filter conditions keyed by fully qualified field name. Filter values vary by field type.
      - `limit` integer — Maximum number of rows to return.
      - `sorts` AiQuerySort[] — Sort specifications applied to the query results.
        - `column_name` string, required — Fully qualified field name to sort by (e.g., "view_name.field_name").
        - `sort_descending` boolean, required — Whether to sort in descending order.
      - `table` string — The base topic or view name for the query.
    - `verification` object, nullable — What Omni observed while verifying the replacement condition, null when condition.verify was false, and absent when the request did not derive a condition.
      - `conditionMetNow` boolean — Whether the condition held when Omni verified it. Present only for RESULTS_PRESENT and RESULTS_MISSING.
      - `rowCount` integer, required — Rows the condition query returned when Omni verified it.
  - `createdAt` string, required — ISO 8601 timestamp when the routine was created.
  - `description` string, nullable, required — Display-only notes about the routine, or null.
  - `destination` union, required — Delivery configuration for the routine.
    - RoutineEmailDestinationResponse
      - `recipientEmails` string[], required — Email addresses configured as direct recipients of each scheduled run, resolved from their current membership.
      - `type` 'email', required — Selects email delivery — each scheduled run is sent to the listed email recipients and user groups.
      - `userGroupIds` string[], required — User group IDs whose active members receive each scheduled run. Omni expands each group to the members' current email addresses when the routine runs.
    - RoutineSlackDestination
      - `recipientId` string, required — The Slack channel ID (e.g. "C01234567") or user ID (e.g. "U01234567") that receives each scheduled run. Exactly one recipient per Slack routine.
      - `slackRecipientType` 'channel' | 'users', required — Whether `recipientId` is a Slack channel or a user (delivered as a direct message).
      - `type` 'slack', required — Selects Slack delivery — each scheduled run is posted to one Slack channel or sent as a direct message to one user.
  - `disabled` boolean, required — Whether the owner has paused the routine.
  - `id` string, uuid, required — The unique identifier of the routine.
  - `lastRun` RoutineLastRun, nullable, required — Most recent completed run, or null if the routine has never completed a run.
    - `completedAt` string, nullable, required — ISO 8601 timestamp the last completed run finished.
    - `label` string, required — Customer-visible status of the last completed run.
    - `state` string, required — Machine-readable status of the last completed run.
  - `modelId` string, uuid, required — The model the prompt runs against.
  - `name` string, required — Customer-visible name of the routine. Used as the email subject for email destinations, and shown on Slack deliveries.
  - `prompt` string, required — Natural language prompt Omni runs on each scheduled run.
  - `recipientCount` integer, required — Number of distinct deliverable recipients. For email, user groups are expanded to members and duplicates removed; a Slack routine is always 1 (its single channel or DM).
  - `schedule` string, required — Six-field cron expression (minute, hour, day-of-month, month, day-of-week, year; use `?` for an unspecified day field).
  - `systemDisabled` boolean, required — Whether Omni disabled the routine because it could no longer run successfully or safely.
  - `systemDisabledReason` string, nullable, required — Reason Omni disabled the routine, or null.
  - `timezone` string, required — IANA timezone identifier used to evaluate the schedule.
  - `topicName` string, nullable, required — Topic scoping query generation, or null.
  - `updatedAt` string, required — ISO 8601 timestamp when the routine was last updated.

## Other responses

- `400` — Invalid routine ID, request body, recipient configuration, schedule, or timezone. Also returned when a supplied destination's type is disabled by the organization's delivery destination settings, when Omni could not compose a working replacement condition, or when requested verification failed. Condition failures include a stable `code`: `not_expressible`, `no_query`, `malformed_query`, or `dry_run_failed`. Nothing is updated on these failures.
- `401` — Missing or invalid API key.
- `402` — Composing or verifying the replacement condition needs AI, and the organization is over its AI credit limit. The body carries the stable reason code `shutoff`.
- `403` — AI routines, AI query generation, or conditional routines are not enabled for the organization; the routine owner lacks AI access to its model; or a user-scoped API key tried to update another user's routine.
- `404` — Routine or routine-owner membership not found, or the routine has been deleted.
- `503` — An AI or query service was temporarily unavailable while composing or verifying the replacement condition. Retryable.

---

[API](https://skmtc.dev/omniapp/apis/omni-api.md) · [All operations](https://skmtc.dev/omniapp/apis/omni-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/omniapp/omni-api/revisions/2ed3f36eff42/schema)
