---
title: "Create a routine"
method: POST
path: "/api/v1/ai/routines"
tags: ["AI Routines"]
---

# Create a routine

`POST /api/v1/ai/routines`

Create a routine that runs a saved prompt on a schedule and delivers the AI response through a single destination — email (one or more recipients / user groups) or Slack (a single channel or direct message). Each scheduled run executes once using the routine owner's permissions, and every recipient receives the same result. Organization API keys can pass `?userId=<membershipId>` to create the routine for a specific organization member.

## Query parameters

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

## Request body

- RoutineCreateBody
  - `branchId` string, uuid — Optional branch ID for the model. Must be a branch of the shared model specified by modelId.
  - `description` string — Optional human-readable notes about the routine. Display-only — never used as model input.
  - `gating` 'auto' | 'alert' | 'unconditional' — Deprecated. Delivery conditions are no longer derived from the prompt. 'auto' (the default) and 'unconditional' create a routine that delivers on every scheduled run. 'alert' declares a delivery condition Omni cannot honor from the prompt alone and fails with code no_condition_detected.
  - `modelId` string, uuid, required — The UUID of the model the prompt runs against. Must be a shared model, or a shared-extension model usable as a workbook base.
  - `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.
  - `schedule` string, required — 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; contact Omni support if you need more frequent scheduling.
  - `timezone` string, required — IANA timezone identifier used to evaluate the schedule.
  - `topicName` string — Topic name to scope query generation. If omitted, the AI picks the best topic.
  - `destination` union, required — Single delivery destination for the routine. To send results to multiple destinations, create one routine per destination. Omni runs the prompt once per scheduled run using the routine owner's permissions, and every recipient receives the same result regardless of their own permissions.
    - RoutineEmailDestination
      - `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.
    - 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.

## Response `201`

Routine created successfully.

- RoutineCreateResponse
  - `id` string, uuid, required — The unique identifier for the newly created routine.

## Other responses

- `400` — Invalid request body, recipient configuration, schedule, or timezone. Also returned when the schedule is more frequent than the organization allows, and, with code `no_condition_detected`, for `gating: "alert"` (no delivery condition can be honored from the prompt alone).
- `401` — Missing or invalid API key.
- `403` — AI routines or AI query generation are not enabled for the organization, the API key cannot act on behalf of the requested user, the request used `gating: "alert"` but conditional routines are not enabled for the organization, or the target user is an embed user (embed users cannot own routines).
- `404` — Model, branch, or topic not found, or not accessible to the requested user. Also returned when the `userId` membership has not accepted its invitation to the organization yet.
- `429` — The resolved user already has the maximum number of active routines.

---

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