> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployments

> Run an agent on a cron schedule.

A **deployment** runs an [agent](https://vetta.sh/docs/api/agents.md) automatically on a cron schedule. Each fire creates a new [session](https://vetta.sh/docs/api/sessions.md) from a fixed first input (`input_template`), subject to its own budget. Use deployments for recurring, unattended work.

## The deployment object

**id** `string`

Unique id (e.g. `dep_01H...`).

**agent\_id** `string`

The agent to run.

**agent\_version** `integer | null`

Pinned [agent version](https://vetta.sh/docs/api/agents.md#the-agent-version-object) each run uses. `null` means every fire tracks the agent's `current_version`. A pin on the version an update or rollback replaces moves up to the new version; a pin on any older version stays.

**cron** `string`

Cron expression defining the schedule, read in `timezone`.

**timezone** `string`

IANA zone the `cron` is read in (default: the [organization's `timezone`](https://vetta.sh/docs/api/organizations)), so `0 9 * * 1` stays 09:00 local across a daylight-saving shift.

**input\_template** `string`

Text used as the session's first input on each run. The input ends with the time the run was scheduled for (or, for `POST /v1/deployments/{id}/run`, when it started), in the deployment's timezone and in UTC, so a template can say "since the last run".

**budget\_micro\_usd** `integer`

Per-run session budget, in micro-USD. Always set — it is required at create. `0` means none of its own: each fire runs on the agent's `budget.max_task_micro_usd`.

**window** `string`

Completion window for scheduled runs.

**on\_idle** `string | null`

URL POSTed with the `session.idle` envelope when a fire goes idle. A non-null value has a [webhook endpoint](https://vetta.sh/docs/api/webhooks.md) behind it, listed by `GET /v1/webhooks` with `events: ["deployment.on_idle"]`; `POST /v1/webhooks/{id}/rotate` returns the secret these deliveries are signed with, and `GET /v1/webhooks/{id}/deliveries` is their log. This field is the authority: if the endpoint behind it is re-pointed elsewhere, the push is refused rather than sent to the other URL.

**identity** `string | null`

The [persona](https://vetta.sh/docs/identity/personas.md) every fire speaks as, as an `idn_` id. `null` runs each fire as no persona.

**enabled** `boolean`

Whether the schedule is active — what you asked for.

**schedule\_status** `string`

Whether anything will act on it — what you get. `scheduled` (a clock is watching it), `paused` (`enabled: false`), or `unscheduled` (enabled, but no clock runs schedules on this installation, so it will never fire on its own).

**next\_run\_at** `string | null`

Next fire time, and **`null` unless `schedule_status` is `scheduled`** — a date nothing will honour is worse than none. An `unscheduled` deployment still fires on demand with `POST /v1/deployments/{id}/run`.

**created\_at** `string`

Creation timestamp.

## Create a deployment

`POST /v1/deployments` → `201 Created`.

**agent\_id** `string` *required*

The agent to run on schedule.

**agent\_version** `integer`

Pin runs to a specific agent version for staged rollout or rollback. Omit to always track the agent's `current_version`. To hold a schedule back while the agent changes, pin a version older than the current one: a pin on the current version follows the next update.

**cron** `string` *required*

Cron expression (e.g. `0 9 * * 1` = Mondays at 09:00), read in `timezone`.

**timezone** `string`

IANA zone the `cron` is read in. Defaults to the [organization's `timezone`](https://vetta.sh/docs/api/organizations), not UTC: a routine created without one runs on the company's clock.

**input\_template** `string` *required*

The input each run sends to its session.

**budget\_micro\_usd** `integer` *required*

Per-run budget in micro-USD. It must be stated. `0` runs each fire on the agent's own task budget (`budget.max_task_micro_usd`), the ceiling any session of that agent has.

**window** `string`

Completion window (`immediate | priority | loose`). Defaults to the agent's window.

**on\_idle** `string`

URL POSTed with the `session.idle` envelope each time a fire goes idle. Defaults to `null`, which pushes nothing. Setting it provisions the webhook endpoint the pushes are delivered through, so they inherit the signature, the retry schedule, the auto-disable and the delivery log.

**identity** `string`

The [persona](https://vetta.sh/docs/identity/personas.md) every fire speaks as — an `idn_` id **or** the persona's name, exactly as when creating a [session](https://vetta.sh/docs/api/sessions.md). The agent must already hold a grant to it. It is resolved at create and stored as the id, so the response echoes `idn_…` even when you sent a name, and renaming the persona later cannot re-point the schedule. Defaults to `null`: the fire runs as no persona.

**enabled** `boolean`

Start active. Defaults to `true`.

```bash cURL theme={"system"}
curl -fsSL https://api.vetta.sh/v1/deployments \
  -H "authorization: Bearer sk_live_..." \
  -H "content-type: application/json" \
  -H "idempotency-key: $(uuidgen)" \
  -d '{
    "agent_id": "agt_01H8XK...",
    "agent_version": 2,
    "cron": "0 9 * * 1",
    "input_template": "Summarize last week'\''s refunds and publish a report.",
    "budget_micro_usd": 3000000,
    "window": "loose"
  }'
```

```json Response theme={"system"}
{
  "id": "dep_01H9EF...",
  "object": "deployment",
  "agent_id": "agt_01H8XK...",
  "agent_version": 2,
  "cron": "0 9 * * 1",
  "input_template": "Summarize last week's refunds and publish a report.",
  "budget_micro_usd": 3000000,
  "window": "loose",
  "timezone": "America/New_York",
  "on_idle": null,
  "identity": null,
  "enabled": true,
  "schedule_status": "scheduled",
  "next_run_at": "2026-08-24T13:00:00Z",
  "created_at": "2026-08-20T17:00:00Z"
}
```

## Retrieve & list

```bash theme={"system"}
GET /v1/deployments/{id}   # retrieve one -> 200
GET /v1/deployments        # list (cursor-paginated) -> 200
```

See [Pagination](https://vetta.sh/docs/api/pagination.md).

## Update a deployment

`PATCH /v1/deployments/{id}` → `200 OK`. Scope `agents:write`. A partial update — send only the fields you are changing.

Every field of the deployment is patchable **except `agent_id`**: repointing a schedule at a different agent would silently change what the cron does while keeping its history, so create a new deployment instead.

**cron** `string`

New cron expression. Recomputes `next_run_at`.

**timezone** `string`

IANA zone the cron is read in.

**input\_template** `string`

The message each fire starts with.

**agent\_version** `integer`

Pin a different agent version.

**budget\_micro\_usd** `integer`

Per-run cap, in micro-USD.

**on\_idle** `string`

The idle-push URL, or `null` to stop pushing — `null` deletes the endpoint behind it and its signing secret. A new URL re-points the endpoint and re-enables it, so this is how a target that auto-disabled after repeated failures is brought back.

**identity** `string`

The persona each fire speaks as, or `null` to run as none. Re-validated against the agent's grants.

**enabled** `boolean`

The schedule switch — the same state [pause and resume](#pause--resume) toggle.

```bash theme={"system"}
curl -fsSL -X PATCH https://api.vetta.sh/v1/deployments/dep_01H9EF... \
  -H "authorization: Bearer sk_live_..." \
  -H "content-type: application/json" \
  -d '{ "cron": "0 9 * * 1-5", "timezone": "Europe/London" }'
```

Returns the full deployment object, including the recomputed `next_run_at` and `schedule_status`.

**Errors** — `validation_failed` (400) for an unparseable cron, an unknown timezone, an attempt to change `agent_id`, or an `identity` the agent does not hold; `not_found` (404), including an `identity` that does not exist.

## Pause & resume

`POST /v1/deployments/{id}/pause` and `POST /v1/deployments/{id}/resume` → `200 OK`. Toggle the schedule without deleting the deployment.

```json Response theme={"system"}
{ "id": "dep_01H9EF...", "enabled": false, "schedule_status": "paused", "next_run_at": null }
```

## Run once, now

`POST /v1/deployments/{id}/run` → `202 Accepted`. Fires the deployment immediately, whatever its schedule says — including while it is `paused` or `unscheduled`. Every fire, scheduled or manual, is an ordinary session carrying this deployment's `deployment_id`.

## List runs

`GET /v1/deployments/{id}/runs` → `200 OK`. Lists the sessions produced by this deployment, newest first. Cursor-paginated.

```json Response theme={"system"}
{
  "data": [
    { "session_id": "ses_01H9GG...", "status": "idle", "started_at": "2026-08-24T09:00:02Z" }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## Delete a deployment

`DELETE /v1/deployments/{id}` → `200 OK`. Removes the schedule. Sessions it already created are retained.

```json Response theme={"system"}
{ "id": "dep_01H9EF...", "object": "deployment", "deleted": true }
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.