---
title: "Create task"
method: POST
path: "/tasks"
tags: ["Tasks"]
---

# Create task

`POST /tasks`

## Request

- Base URL: `https://api.crevio.co/v1`
- URL: `https://api.crevio.co/v1/tasks`
- Auth: API key in header `Authorization`

Creates a new AI task. Use trigger_type to schedule it: `immediate` runs once right away, `cron` runs on a cron expression, `interval` runs every N seconds, `once` runs at a specific scheduled_at, `event` runs in response to account events, including another task finishing: `event_conditions: {event_type: "task_run.completed", after_task_id: "task_..."}` runs it after each real run of that task completes, so a step that depends on another never needs a polling schedule. For recurring tasks (`cron`/`interval`), add an optional `condition_script` — a cheap JavaScript gate that runs before each fire (no LLM, no credits) and skips the run unless its last expression is truthy, so the agent only wakes when there's work to do.

## Headers

- `Idempotency-Key` string

## Request body

- AiTaskRequest
  - `name` string
  - `description` string, nullable
  - `kind` 'agent' | 'script': `agent` runs `prompt` as an agent turn. `script` runs `script` on the account's computer with no agent and no model credits, for runs that are the same deterministic steps every time; it takes no `prompt`. To switch kind, send the new `kind` with its field and `null` for the other.
  - `prompt` string, nullable: What the agent does on each run. Required for `kind: agent`, must be absent for `kind: script`.
  - `success_criteria` string, nullable: What done means for one run: the checkable outcomes a finished run must have produced (a post is live at its URL, the report reached #sales, every new order has a tracking number). Every run is shown them and must check its result against them before it reports. Outcomes, not steps; the steps belong in `prompt`.
  - `trigger_type` 'immediate' | 'cron' | 'interval' | 'once' | 'event'
  - `cron_expression` string, nullable
  - `interval_seconds` integer, nullable
  - `scheduled_at` string, date-time, nullable
  - `timezone` string
  - `model_id` string, nullable
  - `agent` 'business' | 'engineering': Which agent runs the task. Use `engineering` for pure code/build work on a site; defaults to `business`.
  - `condition_script` string, nullable: Cheap pre-run gate for recurring tasks (`cron`/`interval`). Plain JavaScript run in a sandboxed isolate against the same `crevioApi.*` connector as the execute tool, BEFORE each scheduled run — no LLM, no credits. The task only runs when the script's last expression (or explicit `return`) is truthy; it skips on `false`/`null`. **Default to setting this whenever the task is "act only when X"** (new/unfulfilled/failed records, a threshold crossed, an unread inbox, a metric at zero) — without it the agent wakes and spends credits on every tick even when there's nothing to do. Only omit it for tasks that genuinely should run every tick (e.g. a scheduled report the user always wants). End with a boolean, e.g. `const r = await crevioApi.listOrders({ status: 'succeeded' }); r.data.some(o => o.fulfillment_status !== 'fulfilled')`. Errors fail open (the task runs). Ignored for non-recurring triggers.
  - `pre_run_script` string, nullable
  - `script` string, nullable: JavaScript run on the account's computer on each run; its logs and return value become the run's summary. Required for `kind: script`, must be absent for `kind: agent`.
  - `approval_mode` 'autonomous' | 'supervised' | 'read_only'
  - `expires_at` string, date-time, nullable
  - `active` boolean
  - `visibility` 'account' | 'personal'
  - `max_runs_per_day` integer, nullable: Event tasks only: at most this many runs started by events per calendar day, in the account's time zone. Every further event that day is recorded as a skipped run (`skip_reason: rate_limited`) and starts nothing, webhook deliveries included. Test runs don't count. Set it whenever the user names a daily cap; `null` removes it.
  - `min_interval_seconds` integer, nullable: Event tasks only: cooldown after a run started by an event. An event within this many seconds of that run is recorded as a skipped run (`skip_reason: rate_limited`) and starts nothing. Set it whenever the user says "at most once every N minutes"; `null` removes it.
  - `delivery_methods` string[]: Where each run's result is delivered. Omit it to get the default, in-app notification plus email; set it only when the user asked for a specific channel. `[]` delivers nowhere.
  - `event_conditions` object, nullable: Event tasks only: what starts a run. `event_type` is one event from GET /v1/events. To run after another task finishes, use `{event_type: "task_run.completed", after_task_id: "task_..."}` (or `task_run.failed` to run when it fails): each real run of that task that finishes starts this one, and the run receives the finished run (id, summary, status) as `event.data.object`. Test runs start nothing. A chain that loops back on itself or runs longer than 5 tasks is refused. `email_message.*` events also take `inbox_id`; `external.slack.*` events take `channel_id`, `from_user_id`, `reaction` and `channel_type`; `external.discord.*` events (`message`, `mention`, `reaction_added`) take `channel_id`, `from_user_id`, `emoji` and `guild_id`.
  - `site_id` string: Site this task works on (`site_...`); its repo is mounted as the run's workspace. Defaults to the account's default working site.

## Response `201`

Task created

- AiTask
  - `id` string, required
  - `object` string, required
  - `name` string, required
  - `description` string, nullable, required
  - `kind` 'agent' | 'script', required
  - `prompt` string, nullable, required
  - `success_criteria` string, nullable, required
  - `trigger_type` 'immediate' | 'cron' | 'interval' | 'once' | 'event', required
  - `cron_expression` string, nullable, required
  - `interval_seconds` integer, nullable, required
  - `scheduled_at` string, date-time, nullable, required
  - `event_conditions` object, nullable, required
  - `condition_script` string, nullable, required
  - `pre_run_script` string, nullable, required
  - `script` string, nullable, required
  - `timezone` string, required
  - `delivery_methods` string[], required
  - `approval_mode` 'autonomous' | 'supervised' | 'read_only', required
  - `model_id` string, nullable, required
  - `agent` 'business' | 'engineering', required
  - `visibility` 'account' | 'personal', required
  - `active` boolean, required
  - `expires_at` string, date-time, nullable, required
  - `next_run_at` string, date-time, nullable, required
  - `last_run_at` string, date-time, nullable, required
  - `total_runs_count` integer, required
  - `consecutive_failure_count` integer, required
  - `total_credits_consumed` integer, required
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `max_runs_per_day` integer, nullable, required: Event tasks: the most event-started runs per day (account time zone); later events are skipped as `rate_limited`.
  - `min_interval_seconds` integer, nullable, required: Event tasks: the cooldown after an event-started run; events inside it are skipped as `rate_limited`.
  - `site_id` string, nullable, required
  - `source` 'user' | 'agent' | 'system', required: How the task came to exist: `user` (a person made it in the dashboard), `agent` (the agent made it inside the chat `origin_chat_id`, whose person is `created_by_id`), or `system` (a built-in task).
  - `created_by_id` string, nullable, required: The person (`user_...`) who made the task or asked for it. Null for built-in tasks.
  - `created_by_name` string, nullable, required
  - `origin_chat_id` string, nullable, required: The chat (`aichat_...`) the task was set up in. A member's chat opens only for that member.
  - `recent_runs` AiTaskRunSummary[], required: The task's newest executed runs (at most 5, newest first; skipped and test runs excluded).
    - `id` string, required
    - `status` 'pending' | 'running' | 'completed' | 'failed' | 'needs_input' | 'timed_out' | 'unknown' | 'skipped', required
    - `created_at` string, date-time, required
    - `completed_at` string, date-time, nullable, required
    - `error_message` string, nullable, required
    - `chat_id` string, nullable, required

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `422`: Validation error
- `429`: Rate limit exceeded — 600 requests per minute per credential. Retry after the number of seconds in `Retry-After`.
- `500`: Internal server error

---

[API](https://skmtc.dev/crevio/apis/crevio-api-v1.md) · [All operations](https://skmtc.dev/crevio/apis/crevio-api-v1/llms.txt) · [OpenAPI document](https://skmtc.dev/crevio/apis/crevio-api-v1/revisions/2219f18ad651?raw)
