# Update Task

Source: https://recoupable.dev/docs/api-reference/tasks/update

Update scheduled task

## PATCH /api/tasks

Full OpenAPI specification: https://recoupable.dev/docs/spec/releases.json

## Authentication

This operation requires one of the security alternatives in the specification below. Security scheme definitions are included where present in the published specification.

[Authentication guide](https://recoupable.dev/docs/authentication)

## Operation and referenced schemas

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Recoup API - Releases",
    "description": "API documentation for the Recoup platform - an AI agent platform for the music industry",
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.recoupable.dev"
    }
  ],
  "paths": {
    "/api/tasks": {
      "patch": {
        "summary": "Update scheduled task",
        "description": "Update an existing scheduled task. Only the id field is required; any additional fields you include will be updated on the task. The response shape matches the GET endpoint (an array containing the updated task).",
        "security": [
          {
            "apiKeyAuth": []
          },
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "description": "JSON object with `id` and optional fields to merge onto the task.",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTaskRequest"
              },
              "examples": {
                "updateTitleAndSchedule": {
                  "summary": "Change title and cron",
                  "value": {
                    "id": "aade2bce-55c7-468e-a606-c4e76fb2ea2a",
                    "title": "Weekly Genre Pulse Check (rev)",
                    "schedule": "0 10 * * 4"
                  }
                },
                "toggleEnabled": {
                  "summary": "Pause or resume a task",
                  "value": {
                    "id": "aade2bce-55c7-468e-a606-c4e76fb2ea2a",
                    "enabled": false
                  }
                },
                "changeModel": {
                  "summary": "Switch model only",
                  "value": {
                    "id": "aade2bce-55c7-468e-a606-c4e76fb2ea2a",
                    "model": "claude-sonnet-4-20250514"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task updated successfully. Body is a `TasksResponse` with the updated task in `tasks` (typically one task).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TasksResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request — missing `id`, empty strings where a field is provided, or other validation failure from the request body. The body reports the first Zod issue via `missing_fields` and `error`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateTaskValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Payment required - the account's plan does not allow this task. `limit` is `task_count` when the account already has `task_limit` enabled tasks, or `min_cadence` when the cron schedule fires more often than `min_cadence_minutes` allows. Nothing is written; upgrade at `billingUrl`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanLimitError"
                },
                "examples": {
                  "taskCount": {
                    "summary": "Free account re-enabling a disabled task while another is enabled",
                    "value": {
                      "status": "error",
                      "error": "plan_limit",
                      "limit": "task_count",
                      "message": "Free includes 1 task. Starter includes 3, Pro is unlimited.",
                      "plan": "free",
                      "task_limit": 1,
                      "min_cadence_minutes": 10080,
                      "current_task_count": 1,
                      "billingUrl": "https://app.recoupable.dev/plan"
                    }
                  },
                  "minCadence": {
                    "summary": "Free account changing a task to a daily schedule",
                    "value": {
                      "status": "error",
                      "error": "plan_limit",
                      "limit": "min_cadence",
                      "message": "Free runs tasks weekly at most. Starter runs daily, Pro runs hourly.",
                      "plan": "free",
                      "task_limit": 1,
                      "min_cadence_minutes": 10080,
                      "current_task_count": 0,
                      "billingUrl": "https://app.recoupable.dev/plan"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - account_id is outside caller authorization scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No task exists with the given `id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateTaskFailureResponse"
                },
                "examples": {
                  "notFound": {
                    "summary": "Unknown task id",
                    "value": {
                      "status": "error",
                      "error": "Task not found"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error while updating the task or syncing the Trigger.dev schedule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateTaskFailureResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "UpdateTaskRequest": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the task to update",
            "example": "aade2bce-55c7-468e-a606-c4e76fb2ea2a"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "New descriptive title. If sent, must be a non-empty string.",
            "example": "Weekly Genre Pulse Check (Updated)"
          },
          "prompt": {
            "type": "string",
            "minLength": 1,
            "description": "New instruction/prompt executed by the task. If sent, must be a non-empty string.",
            "example": "Execute this weekly genre analysis workflow and email a summary to the team."
          },
          "schedule": {
            "type": "string",
            "minLength": 1,
            "description": "New cron expression. If sent, must be non-empty and valid for your environment.",
            "example": "0 10 * * 4"
          },
          "timezone": {
            "type": "string",
            "description": "Optional IANA time zone the cron is interpreted in (DST-aware). If sent, updates the Trigger.dev schedule; a timezone-only change re-syncs the schedule. A cron-only update preserves the existing time zone.",
            "example": "America/New_York"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the account to update the task for. Only applicable when the authenticated account has access to multiple accounts via organization membership. If not provided, the task is updated for the API key's own account.",
            "example": "848cd58d-700f-4b38-ab4c-d9f52a1b2c3d"
          },
          "artist_account_id": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of the artist account to associate with the task after update",
            "example": "1873859c-dd37-4e9a-9bac-80d35a1b2c3d"
          },
          "enabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the task is enabled (`true` / `false`), or `null` to clear an explicit override depending on server rules.",
            "example": true
          },
          "model": {
            "type": "string",
            "minLength": 1,
            "description": "AI model identifier to use when the task runs. If sent, must be a non-empty string.",
            "example": "claude-sonnet-4-20250514"
          }
        }
      },
      "TasksResponse": {
        "type": "object",
        "required": [
          "status",
          "tasks"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "description": "Array of task objects"
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is error)"
          }
        }
      },
      "UpdateTaskValidationErrorResponse": {
        "type": "object",
        "required": [
          "status",
          "missing_fields",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Always `error` when validation fails"
          },
          "missing_fields": {
            "type": "array",
            "description": "JSON path segments to the first field that failed validation (from Zod), e.g. `[\"id\"]` or `[\"schedule\"]`",
            "items": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            }
          },
          "error": {
            "type": "string",
            "description": "Validation message for the first failing field"
          }
        }
      },
      "Error": {
        "required": [
          "error",
          "message"
        ],
        "type": "object",
        "properties": {
          "error": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "PlanLimitError": {
        "type": "object",
        "required": [
          "status",
          "error",
          "limit",
          "message",
          "plan",
          "task_limit",
          "min_cadence_minutes",
          "current_task_count",
          "billingUrl"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Always `error` for this response shape"
          },
          "error": {
            "type": "string",
            "enum": [
              "plan_limit"
            ],
            "description": "Machine-readable code. Literally `plan_limit`."
          },
          "limit": {
            "type": "string",
            "enum": [
              "task_count",
              "min_cadence"
            ],
            "description": "Which entitlement blocked the request: `task_count` (the plan's enabled-task cap is reached) or `min_cadence` (the cron fires more often than the plan allows)."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation naming the plan and the limit, suitable to show to a user.",
            "example": "Free includes 1 task. Starter includes 3, Pro is unlimited."
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "starter",
              "pro"
            ],
            "description": "The account's current plan, resolved from its subscription."
          },
          "task_limit": {
            "type": "integer",
            "nullable": true,
            "minimum": 1,
            "description": "Maximum enabled tasks on the current plan. Null means uncapped.",
            "example": 1
          },
          "min_cadence_minutes": {
            "type": "integer",
            "minimum": 1,
            "description": "Shortest allowed gap between two consecutive runs of a task on the current plan, in minutes (Free 10080, Starter 1440, Pro 60).",
            "example": 10080
          },
          "current_task_count": {
            "type": "integer",
            "minimum": 0,
            "description": "Enabled tasks the account has right now, excluding the one being created or updated.",
            "example": 1
          },
          "billingUrl": {
            "type": "string",
            "format": "uri",
            "description": "Static link to `/plan` in the Recoup app, where a human can upgrade. Constant; retrying creates nothing.",
            "example": "https://app.recoupable.dev/plan"
          }
        }
      },
      "UpdateTaskFailureResponse": {
        "type": "object",
        "required": [
          "status",
          "error"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ],
            "description": "Always `error` for this response shape"
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message (for example `Task not found` on 404)"
          }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the task"
          },
          "title": {
            "type": "string",
            "description": "Descriptive title or name of the task"
          },
          "prompt": {
            "type": "string",
            "description": "Detailed instruction or prompt for task execution"
          },
          "schedule": {
            "type": "string",
            "description": "Cron expression defining when the task should execute (e.g., '0 10 * * *')"
          },
          "timezone": {
            "type": "string",
            "nullable": true,
            "description": "IANA time zone the task's cron is interpreted in, read from the Trigger.dev schedule (the source of truth). Null when the task has no schedule or the timezone can't be read.",
            "example": "America/New_York"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the associated account"
          },
          "artist_account_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for the associated artist account"
          },
          "enabled": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the task is enabled. Defaults to true."
          },
          "trigger_schedule_id": {
            "type": "string",
            "nullable": true,
            "description": "Identifier for the trigger schedule associated with this task"
          },
          "recent_runs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskRunResponse"
            },
            "description": "Last 5 runs for this task, sourced from the Trigger.dev API."
          },
          "upcoming": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Next scheduled run times."
          },
          "owner_email": {
            "type": "string",
            "nullable": true,
            "description": "Primary email address for the task owner account when one exists."
          },
          "artist_name": {
            "type": "string",
            "nullable": true,
            "description": "Display name of the artist account the task runs for (`artist_account_id`), so a task list can label rows without a roster lookup. Null when the artist account no longer exists.",
            "example": "Braden Bales"
          },
          "model": {
            "type": "string",
            "nullable": true,
            "minLength": 1,
            "description": "AI model identifier used when the task runs. When present as a string, must be non-empty; otherwise `null` if unset."
          }
        }
      },
      "TaskRunResponse": {
        "type": "object",
        "description": "Raw Trigger.dev SDK run object. The API passes through the SDK response without field mapping. See https://trigger.dev/docs/management/runs/retrieve for the full reference. When listing runs, `output`, `error`, `payload`, and `attempts` are not included.",
        "required": [
          "id",
          "status",
          "taskIdentifier",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique run identifier, prefixed with `run_`"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING_VERSION",
              "DELAYED",
              "QUEUED",
              "EXECUTING",
              "REATTEMPTING",
              "FROZEN",
              "COMPLETED",
              "CANCELED",
              "FAILED",
              "CRASHED",
              "INTERRUPTED",
              "SYSTEM_FAILURE"
            ],
            "description": "Current run status"
          },
          "taskIdentifier": {
            "type": "string",
            "description": "The task type identifier (e.g. 'setup-sandbox', 'run-sandbox-command')"
          },
          "idempotencyKey": {
            "type": "string",
            "nullable": true,
            "description": "Idempotency key used to deduplicate trigger requests"
          },
          "version": {
            "type": "string",
            "description": "The worker version that executed the run"
          },
          "isTest": {
            "type": "boolean",
            "description": "Whether this is a test run"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run was created (ISO 8601)"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run was last updated (ISO 8601)"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When execution started (null if not yet started)"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the run finished (null if still running)"
          },
          "delayedUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "If delayed, when the run becomes eligible to execute"
          },
          "ttl": {
            "description": "Time-to-live. If the run is not started within this duration, it expires.",
            "nullable": true
          },
          "expiredAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "When the run expired (null if not expired)"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Tags associated with this run (max 10)"
          },
          "metadata": {
            "type": "object",
            "nullable": true,
            "description": "JSON metadata attached to the run"
          },
          "costInCents": {
            "type": "number",
            "description": "Compute cost of the run in cents"
          },
          "baseCostInCents": {
            "type": "number",
            "description": "Base invocation cost in cents"
          },
          "durationMs": {
            "type": "number",
            "description": "Compute duration in milliseconds"
          },
          "env": {
            "type": "object",
            "description": "Environment the run executed in",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "user": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "depth": {
            "type": "integer",
            "description": "Nesting depth for child runs"
          },
          "batchId": {
            "type": "string",
            "nullable": true,
            "description": "Batch ID if triggered as part of a batch"
          },
          "triggerFunction": {
            "type": "string",
            "enum": [
              "trigger",
              "triggerAndWait",
              "batchTrigger",
              "batchTriggerAndWait"
            ],
            "description": "The function used to trigger this run"
          },
          "payload": {
            "description": "Input payload for the task. Only present when retrieving by runId.",
            "nullable": true
          },
          "output": {
            "description": "Task output data. Only present when retrieving by runId, and only populated when `status` is `COMPLETED`. Shape varies by `taskIdentifier`. The `create-content` task returns the schema below; other tasks return their own.",
            "nullable": true,
            "oneOf": [
              {
                "$ref": "#/components/schemas/CreateContentRunOutput"
              },
              {
                "type": "object",
                "description": "Generic task output (for tasks not yet schema'd)"
              }
            ]
          },
          "error": {
            "type": "object",
            "nullable": true,
            "description": "Error details if the run failed. Only present when retrieving by runId.",
            "properties": {
              "message": {
                "type": "string",
                "description": "Human-readable error message"
              },
              "name": {
                "type": "string",
                "description": "Error name or type"
              },
              "stackTrace": {
                "type": "string",
                "description": "Stack trace"
              }
            }
          },
          "attempts": {
            "type": "array",
            "description": "Attempt history. Only present when retrieving by runId.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Attempt ID, prefixed with `attempt_`"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "PENDING",
                    "EXECUTING",
                    "PAUSED",
                    "COMPLETED",
                    "FAILED",
                    "CANCELED"
                  ]
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "startedAt": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "completedAt": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "error": {
                  "type": "object",
                  "nullable": true,
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "stackTrace": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "schedule": {
            "type": "object",
            "nullable": true,
            "description": "Schedule information if triggered by a schedule. Only present when retrieving by runId."
          },
          "relatedRuns": {
            "type": "object",
            "nullable": true,
            "description": "Related run references (root, parent, children). Only present when retrieving by runId."
          }
        }
      },
      "CreateContentRunOutput": {
        "type": "object",
        "description": "Output payload for a `create-content` task run. Returned in `output` when `status` is `COMPLETED`. Agents should poll `/api/tasks/runs?runId=…` and read these fields once the run is done.",
        "required": [
          "videoSourceUrl",
          "imageUrl",
          "captionText",
          "template"
        ],
        "properties": {
          "videoSourceUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL to the rendered final 9:16 video (image + motion + audio + caption already composed)."
          },
          "imageUrl": {
            "type": "string",
            "format": "uri",
            "description": "URL to the base image used for video generation."
          },
          "captionText": {
            "type": "string",
            "description": "The caption text burned into the video."
          },
          "template": {
            "type": "string",
            "description": "Template id used for this run (e.g. `album-record-store`, `artist-caption-bedroom`).",
            "example": "artist-caption-bedroom"
          },
          "lipsync": {
            "type": "boolean",
            "description": "Whether lipsync was applied (audio-driven mouth animation)."
          },
          "audio": {
            "type": "object",
            "description": "Metadata about the song clip used in the final composition.",
            "properties": {
              "songTitle": {
                "type": "string"
              },
              "songFilename": {
                "type": "string"
              },
              "startSeconds": {
                "type": "number",
                "description": "Offset into the source song where the clip starts."
              },
              "durationSeconds": {
                "type": "number",
                "description": "Length of the audio clip in seconds."
              },
              "clipLyrics": {
                "type": "string",
                "nullable": true,
                "description": "Lyrics for the chosen clip, when available."
              },
              "clipMood": {
                "type": "string",
                "nullable": true,
                "description": "Inferred mood for the chosen clip, when available."
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your Recoup API key. [Learn more](/quickstart#api-keys)."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
```
