---
title: "Update Automation"
method: PUT
path: "/automations/{automationId}"
tags: ["Automations"]
---

# Update Automation

`PUT /automations/{automationId}`

## Request

- Base URL: `https://api.speakai.co/v1`
- URL: `https://api.speakai.co/v1/automations/{automationId}`
- Auth: API key in header `x-speakai-key` and API key in header `x-access-token`

## Update Automation

**Body (JSON):**

``` json
{
 "name": "Updated Marketing Analysis",
 "description": "Enhanced automation with schedule and new assistant type",
 "isActive": true,
 "runType": "schedule",
 "schedule": {
 "timePeriod": "last7days",
 "repeatAt": "09:30"
 },
 "trigger": {
 "type": "folders",
 "folderIds": ["folder123", "folder456"]
 },
 "action": {
 "type": "magic-prompt",
 "magicPrompt": {
 "title": "Weekly Marketing Report",
 "assistantType": "marketer",
 "prompt": "Analyze marketing data and provide insights, trends, and recommendations",
 "assistantTemplateId": "marketing-template-001"
 }
 },
 "fieldId": "marketing-field-123"
}

 ```

## **Key Points:**

• **Path Parameter Required:** `automationId` must be included in the URL path
• **Partial Updates Supported:** You can update only specific fields, not all fields are required
• **Run Type Changes:** When changing to `"schedule"`, include the `schedule` object with `timePeriod` and `repeatAt`
• **Trigger & Action Required:** Both `trigger` and `action` objects appear to be required in the request body
• **Assistant Type:** The `assistantType` is for custom Assistant selected
• **Status Control:** Use `isActive: true/false` to enable or disable the automation
• **Optional Fields:** `fieldId` is optional and only used with magic-prompt actions
• **Schedule Time Periods:** Available options - `"today"`, `"yesterday"`, `"last7days"`, `"last14days"`, `"thisWeek"`
• **Action Types:** Support for `"magic-prompt"` and `"translation"` action types
• **Trigger Types:** Support for `"folders"`, `"tags"`, and `"keywords"` trigger types
• **Assistant Types:** Available options - `"researcher"`, `"marketer"`, `"sales"`, `"general"`, `"recruiter"`, `"custom"`

**Request rules.** The same rules as creating an automation. `schedule` is required only when `runType` is `schedule`, and then both `schedule.timePeriod` and `schedule.repeatAt` are required. Each step's config object has to match that step's `stepType`.

## Path parameters

- `automationId` string, required

## Request body

- object
  - `name` string, required: Name the automation. This is what you see in the automations list. required, max length 150
  - `description` string: Describe what the automation does. You can send an empty string. optional, max length 1000, empty string allowed
  - `isActive` boolean: Turn the automation on or off. Leave it out and the automation keeps whatever active state it already has. optional. The declared default is true, but that default never reaches the controller, which does if (isActive !== undefined) setter.$set.isActive = isActive. Omitting the field therefore leaves the stored value untouched; it does NOT reactivate a paused automation.
  - `runOnceOnly` string: Ignore this field. The server accepts it and then never reads it, so whatever you send has no effect. optional. unconstrained.strip, so any JSON type passes validation. The controller reads runOnceOnly only off the existing stored record, never off your request body, so you cannot set or clear it through this endpoint.
  - `trigger` object, required: Define the single event that starts the automation. required, unknown keys rejected
    - `type` 'folders' | 'tags' | 'keywords' | 'composio' | 'webhook': Pick the kind of event that starts the automation. required inside trigger; values come from the AutomationTrigger list
    - `folderIds` string[]: List the folders the trigger watches. optional, item schema is unconstrained (the schema with no.items)
    - `values` string[]: Send the secondary list a trigger needs, such as the field IDs for a field-updated event. optional, items must be strings, empty strings allowed as items
    - `provider` 'speak' | 'composio': Say which system owns the trigger. optional
    - `app` string: Name the third-party app for a Composio trigger. optional, empty string allowed
    - `triggerSlug` string: Give the provider's slug for the specific trigger you picked. optional, empty string allowed
    - `webhookId` string: Attach an inbound webhook to the trigger by its ID. optional, empty string allowed
    - `childKey` string: Point the trigger at a nested key inside the incoming payload. optional, empty string allowed
    - `connectedAccountId` string: Identify the connected account the trigger authenticates through. optional, empty string allowed, not trimmed and no max length
    - `fieldValueMatches` object[]: Only fire the trigger when the named fields hold the values you list. optional, max 20 entries
      - `fieldId` string: Identify the field to match on. required inside each entry, trimmed, min length 1, max length 100
      - `values` string[]: List the values that count as a match. Send an empty array to match any value. required inside each entry, max 50 items, each item max length 200, empty strings allowed
    - `fieldMatchLogic` 'AND' | 'OR': Choose whether every fieldValueMatches entry has to match or just one. Leaving it out behaves like OR. optional
    - `triggerConfig` object: Pass provider-specific trigger settings. The server stores this object as sent. optional, unconstrained object
  - `triggers` object[]: Add extra alternative triggers. The automation runs when any one of them fires. optional, max 10 entries
    - `type` 'folders' | 'tags' | 'keywords' | 'composio' | 'webhook': Pick the kind of event for this alternative trigger. optional here, unlike trigger.type which is required
    - `folderIds` string[]: List the folders this alternative trigger watches. optional, item schema unconstrained
    - `values` string[]: Send the secondary list this alternative trigger needs. optional, items must be strings, empty strings allowed as items
    - `provider` 'speak' | 'composio': Say which system owns this alternative trigger. optional
    - `app` string: Name the third-party app for this alternative Composio trigger. optional, empty string allowed
    - `triggerSlug` string: Give the provider's slug for this alternative trigger. optional, empty string allowed
    - `fieldValueMatches` object[]: Only fire this alternative trigger when the named fields hold the values you list. optional, max 20 entries, same fieldId and values shape as trigger.fieldValueMatches
    - `fieldMatchLogic` 'AND' | 'OR': Choose whether every fieldValueMatches entry has to match or just one for this alternative trigger. optional
    - `triggerConfig` object: Pass provider-specific settings for this alternative trigger. optional, unconstrained object
    - `connectedAccountId` string: Identify the connected account this alternative trigger authenticates through. optional, trimmed, max length 100, empty string allowed
  - `steps` object[], required: List the steps the automation runs, in order. This replaces the existing steps rather than merging with them. required, min 1 entry, max 20 entries
    - `stepId` string: Give the step an ID that is unique within this automation. Other steps reference it through dependsOn. required, trimmed, min length 1, max length 100
    - `stepType` 'trigger' | 'magic-prompt' | 'translation' | 'composio-action' | 'filter' | 'speak-upload' | 'notify' | 'outbound-webhook' | 'condition': Say what kind of work the step does. This decides which config object the step must carry. required; values come from the AutomationStepType list
    - `magicPrompt` object: Configure an AI prompt step. required when stepType is "magic-prompt", rejected for any other stepType. One step extracts at most 25 fields through fieldIds; send more and the request is rejected with 400. Split a longer rubric across several magic-prompt steps.
      - `title` string: Title the prompt so you can recognize its output later. optional, empty string allowed
      - `modelId` 'gpt-3.5' | 'gpt-3.5-turbo-16k' | 'gpt-3.5-turbo-0125' | 'gpt-4' | 'gpt-4-1106-preview' | 'gpt-4-turbo' | 'gpt-4o-2024-05-13' | 'gpt-4o' | 'gpt-4o-mini' | 'gpt-4o-2024-08-06' | 'gpt-4o-mini-2024-07-18' | 'gpt-4.1-2025-04-14' | 'gpt-5.1-2025-11-13' | 'gpt-5.2' | 'gpt-5.4' | 'gpt-5.4-mini' | 'gpt-5.4-mini-2026-03-17' | 'gpt-5.4-nano' | 'gpt-5.5' | 'gpt-5.5-thinking' | 'gpt-5.6-sol' | 'gpt-5.6-terra' | 'gpt-5.6-luna' | 'claude-2' | 'claude-3-5-sonnet' | 'claude-3-5-sonnet-20241022' | 'claude-3-7-sonnet-latest' | 'claude-haiku-4-5' | 'claude-sonnet-4-6' | 'claude-sonnet-5' | 'claude-opus-4-8' | 'gemini-1.5-pro' | 'gemini-1.5-flash' | 'gemini-2.0-flash' | 'gemini-2.5-pro' | 'gemini-2.5-flash' | 'gemini-2.5-flash-lite' | 'gemini-3-flash-preview' | 'gemini-3.1-flash-lite' | 'gemini-3.1-pro-preview' | 'gemini-3.5-flash' | 'gemini-3.7-flash' | 'gemini-3.8-flash' | 'x-ai/grok-4.5' | 'z-ai/glm-5.2': Override the model for this step. Send an empty string or null to clear it and fall back to your company default. optional; all 43 values copied verbatim from LLMModels. '' and null coerce to absent. empty(the schema) and are not enum members. The enum's header comment says DEPRECATED models are grouped first within each provider and LIVE ones follow, but there is no per-value flag, so no individual value can be marked deprecated from the code.
      - `prompt` string: Write the instruction the model follows. max length 20000; required unless fieldIds is present with at least one entry, in which case an empty string is accepted. The schema.default('') on that branch is not persisted.
      - `assistantType` 'researcher' | 'marketer' | 'sales' | 'general' | 'recruiter' | 'custom': Pick the assistant persona that answers the prompt. Optional, and restricted to the values listed here: any other string is rejected. Omitting it stores no value on the step. When the step runs, the persona falls back to the default saved on the user profile the run belongs to, and to 'general' when none is saved.
      - `assistantTemplateId` string: Identify your custom assistant template. required when assistantType is "custom"; otherwise optional and accepts '' or null. The schema.default('') is not persisted.
      - `isIndividualFolder` boolean: Run the prompt separately per folder instead of once across everything. optional. The schema.default(false) is not persisted.
      - `allowedValues` string[]: Restrict the answer to this list of values. optional, items must be strings, no item cap
      - `allowedValuesMode` 'single' | 'multiple': Choose whether the answer may pick one allowed value or several. optional; values come from AllowedValuesMode. The schema.default('multiple') is not persisted.
      - `otherValues` boolean: Let the answer fall outside the allowed values list. optional
      - `notApplicableValues` string: Say what the model should answer when nothing applies. optional, empty string allowed
      - `fieldId` string: Write the answer into this single field. optional, accepts '' or null
      - `fieldIds` string[]: Extract several fields in one step. Sending at least one field ID makes prompt optional. optional, max 25 items. Over the cap the request is rejected with 400 and the message "A single AI step can extract at most 25 fields. Split the rest into another AI step."
    - `translation` object: Configure a translation step. required when stepType is "translation", rejected for any other stepType
      - `targetLanguage` 'en-US' | 'fr-FR' | 'af-ZA' | 'ar-SA' | 'hy-AM' | 'bg-BG' | 'ca-ES' | 'hr-HR' | 'cs-CZ' | 'da-DK' | 'nl-NL' | 'et-EE' | 'fa-IR' | 'fi-FI' | 'de-DE' | 'el-GR' | 'gu-IN' | 'he-IL' | 'hi-IN' | 'ht-HT' | 'hu-HU' | 'id-ID' | 'is-IS' | 'it-IT' | 'ga-IE' | 'ja-JP' | 'kn-IN' | 'ko-KR' | 'lt-LT' | 'lv-LV' | 'ml-IN' | 'ms-MY' | 'nb-NO' | 'pl-PL' | 'pt-PT' | 'ro-RO' | 'ru-RU' | 'es-ES' | 'sk-SK' | 'sl-SI' | 'sv-SE' | 'ta-IN' | 'te-IN' | 'th-TH' | 'tr-TR' | 'uk-UA' | 'vi-VN' | 'as-IN' | 'ay-BO' | 'bm-ML' | 'eu-ES' | 'be-BY' | 'bho-IN' | 'ceb-PH' | 'co-FR' | 'dv-MV' | 'doi-IN' | 'eo-XX' | 'ee-GH' | 'fil-PH' | 'fy-NL' | 'gl-ES' | 'gn-PY' | 'haw-US' | 'hmn-CN' | 'ig-NG' | 'ilo-PH' | 'jv-ID' | 'km-KH' | 'rw-RW' | 'gom-IN' | 'kri-SL' | 'ku-TR' | 'ckb-IQ' | 'ky-KG' | 'lo-LA' | 'la-VA' | 'ln-CG' | 'lg-UG' | 'lb-LU' | 'mai-IN' | 'mg-MG' | 'mi-NZ' | 'mni-IN' | 'lus-IN' | 'my-MM' | 'ne-NP' | 'ny-MW' | 'or-IN' | 'om-ET' | 'qu-PE' | 'sm-WS' | 'sa-IN' | 'gd-GB' | 'nso-ZA' | 'st-ZA' | 'sn-ZW' | 'sd-PK' | 'si-LK' | 'su-ID' | 'tg-TJ' | 'tt-RU' | 'ti-ER' | 'ts-ZA' | 'tk-TM' | 'ak-GH' | 'ug-CN' | 'xh-ZA' | 'yi-XX' | 'yo-NG' | 'zu-ZA': Pick the language to translate into. required inside translation. The accepted set is TranslationLanguageCodes, defined by mapping the static TranslationLanguages array (lines 6-118) to its transcriptionCode. That array holds 111 entries, so there are exactly 111 accepted values, listed here in source order.
    - `filter` object: Configure a filter step that stops the run when its rules do not match. required when stepType is "filter", rejected for any other stepType
      - `logic` 'AND' | 'OR': Choose whether every rule has to match or just one. optional. The schema.default('AND') is not persisted.
      - `rules` object[]: List the conditions the filter checks. required, min 1 entry, max 20 entries
        - `field` string: Name the field the rule reads. required, trimmed, min length 1, max length 100
        - `op` 'eq' | 'neq' | 'contains' | 'ncontains' | 'startsWith' | 'gt' | 'lt' | 'exists': Pick how the rule compares the field to the value. required
        - `value` string: Give the value to compare against. You can send a string or a number. optional. Declared as a union.max(1000).allow(''), the schema), a string-or-number union.
    - `condition` object: Configure a branching step that sends the run down a true or false path. required when stepType is "condition", rejected for any other stepType; identical shape to steps[].filter
      - `logic` 'AND' | 'OR': Choose whether every rule has to match or just one. optional. The schema.default('AND') is not persisted.
      - `rules` object[]: List the conditions the branch evaluates. required, min 1 entry, max 20 entries, same field, op and value shape as filter rules
    - `composio` object: Configure a step that runs a Composio app action. required when stepType is "composio-action", rejected for any other stepType
      - `app` string: Name the Composio app to act on. required, trimmed, min length 1, max length 100
      - `action` string: Name the action to run in that app. required, trimmed, min length 1, max length 200
      - `connectedAccountId` string: Identify the connected account the action runs as. optional, trimmed, max length 100, empty string allowed
      - `argsTemplate` object: Pass the action's arguments. Values may contain tokens, so the server accepts any shape. optional, unconstrained object
      - `destructive` boolean: Mark the action as destructive so it asks for confirmation. optional
      - `acknowledged` boolean: Confirm you accept a destructive action. optional
    - `speakUpload` object: Configure a step that uploads media into Speak. required when stepType is "speak-upload", rejected for any other stepType
      - `name` string: Name the uploaded media. optional, max length 500, empty string allowed
      - `folderId` string: Choose the folder the upload lands in. In dynamic routing this becomes the fallback folder instead. required (trimmed, min length 1, max length 100) unless folderRouting.mode is "dynamic", in which case it is optional (trimmed, max 100, empty string allowed)
      - `sourceMode` 'url' | 'file': Say whether the upload comes from a URL or from a file already in the run. required
      - `sourceUrl` string: Give the URL to fetch the media from. max length 2000; required when sourceMode is "url", otherwise optional and may be an empty string. Not validated as a URI, because it may carry {{tokens}}.
      - `fieldsMap` object: Map field names to values to set on the uploaded media. optional, keys and values must both be strings
      - `language` string: Set the language for the upload. You can send a language code or a token that resolves at run time, so known codes are not enforced. optional, max length 100, empty string allowed
      - `waitForProcessing` boolean: Hold the automation until the uploaded media finishes processing before the next step runs. optional
      - `folderRouting` object: Route the upload to a folder chosen from the incoming payload instead of a fixed one. optional
        - `mode` 'static' | 'dynamic': Choose between the fixed folderId and a folder picked from the payload. required inside folderRouting
        - `sourceKey` string: Name the payload key that holds the folder to route to. required (trimmed, min length 1, max length 500) when mode is "dynamic"; otherwise optional, trimmed, max length 500, empty string allowed
        - `onNoMatch` 'create' | 'default': Say what to do when no folder matches: create one, or fall back to the folderId. required when mode is "dynamic", otherwise optional
    - `notify` object: Configure a notification step. required when stepType is "notify", rejected for any other stepType
      - `channel` 'in_app' | 'email' | 'slack': Pick where the notification goes. required
      - `target` string: Name the recipient, such as an email address or a Slack channel. optional, max length 500, empty string allowed
      - `message` string: Write the notification body. It may contain {{tokens}}, so the server accepts any text. optional, max length 20000, empty string allowed
      - `emailContent` 'transcript' | 'ai_response': For the email channel, choose what the email carries. optional
    - `outboundWebhook` object: Configure a step that calls a URL of yours. required when stepType is "outbound-webhook", rejected for any other stepType
      - `url` string: Give the URL to call. It may contain {{tokens}}, so it is validated as plain text rather than as a URI. required, trimmed, min length 1, max length 2000, no uri format check
      - `method` 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE': Choose the HTTP method for the call. optional. The schema.default('POST') is not persisted.
      - `headers` object: Set request headers for the call. optional, keys and values must both be strings
      - `bodyTemplate` string: Set the request body. Send either a string template or a JSON object. optional. Declared as a union.max(20000).allow(''), the schema), a string-or-object union.
    - `dependsOn` string[]: List the stepId values that must finish before this step runs. optional, items must be strings
    - `branch` 'true' | 'false': For a step under a condition, say which branch it belongs to. optional. These are the strings "true" and "false", not booleans.
  - `runType` 'instant' | 'schedule' | '': Choose whether the automation runs as soon as its trigger fires or on a schedule. optional, empty string accepted. The controller writes SCHEDULE only when runType strictly equals "schedule" and writes INSTANT otherwise, so omitting it on a scheduled automation converts it back to instant and unsets its schedule.
  - `fieldId` string: Ignore this field. The server validates it and then never reads it, so setting it has no effect. optional. updateAutomation does not destructure a top-level fieldId from req.body.
  - `isUpdated` boolean: Ignore this field. The server always flags the automation as updated for the scheduler on every update, whatever you send. optional. The controller hardcodes isUpdated: true in its $set and never reads the client value.
  - `schedule` object: Set when a scheduled automation runs. required when runType is "schedule", otherwise optional. When runType is not "schedule" the controller unsets any stored schedule.
    - `timePeriod` 'today' | 'yesterday' | 'last7days' | 'last14days' | 'thisWeek': Choose the window of media the scheduled run covers. required when runType is "schedule"; otherwise optional and an empty string is also accepted. Values come from AutomationScheduleTimePeriod.
    - `repeatAt` string: Set the time of day the scheduled run fires. required (trimmed, min length 1) when runType is "schedule"; otherwise optional and an empty string is accepted. No format is enforced.

## Response `200`

Success

---

[API](https://skmtc.dev/speakai/apis/speak-ai-api.md) · [All operations](https://skmtc.dev/speakai/apis/speak-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/speakai/apis/speak-ai-api/revisions/52d777e6d46e?raw)
