---
title: "Automations · intentic sandbox API"
description: "Work the sandbox starts on its own, and the approvals it parks waiting for you. Every route in the automations group of the intentic sandbox API."
url: "https://intentic.dev/api/automations/"
---

Agents

# Automations

Work the sandbox starts on its own, and the approvals it parks waiting for you

**On this page (11 sections)**

- [Things that wake an agent on their own](#automations-list)
- [Create or edit an automation](#automations-upsert)
- [What can trigger an automation here](#automations-catalog)
- [Turn an automation on or off](#automations-setEnabled)
- [Delete an automation](#automations-remove)
- [Rotate an automation's webhook token or intake key](#automations-rotateToken)
- [Fire an automation by hand](#automations-run)
- [Who has written to a listener source](#automations-senders)
- [Automations waiting for a yes](#automations-pendingList)
- [Let a held automation run](#automations-approve)
- [Drop a held automation](#automations-reject)

Scheduled and triggered work: what can trigger one here, what is configured, and switching one on or off, deleting it or firing it by hand. The other half is the approval queue — an automation set to ask first lands there each time it would have run.

11 calls. Pick one to open it, or use the list on the right.

**GET`/automations` Things that wake an agent on their own**

Every automation with its recent runs and when it fires next.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `automations` | object[] |
| `id` The automation's id | string |
| `trigger` What sets it off: a schedule,… | object |
| `when kind is "schedule"` | shape |
| `cron` When, in cron notation | string |
| `tz` Which clock the times in the… | string |
| `afterSessions` Fire only once at least this… | integer |
| `when kind is "once"` | shape |
| `at` The moment it fires, in milliseconds | integer |
| `when kind is "event"` | shape |
| `dailyMax` How many webhook calls a day… | integer |
| `when kind is "listener"` | shape |
| `provider` Which service to listen to | string |
| `channelId` Narrow it to one channel or… | string |
| `eventType` Narrow it to one kind of… | string |
| `mentioned` Only when the agent is actually… | boolean |
| `branch` Narrow it to one branch, for… | string |
| `allowedOrigins` Which websites may reach the public… | string[] |
| `when kind is "workspace"` | shape |
| `event` Which happening | "turn.settled" | "agent.landed" | "deps.broken" | "deps.fixed" |
| `repo` Narrow it to one repository | string |
| `guard` A command run before the wake… | string |
| `prompt` What the woken agent is told | string |
| `webchat` Settings for the public chat widget,… | object |
| `access` Who may write to it | "public" | "google" |
| `requireName` Ask a visitor for a name… | boolean |
| `antiBot` How to keep bots out: a… | "turnstile" | "pow" |
| `turnstileSiteKey` The public half of those keys,… | string |
| `turnstileSecret` The private half, which the sandbox… | string |
| `googleClientId` The site's own sign-in client id | string |
| `title` | string |
| `greeting` | string |
| `accent` | string |
| `position` | "top-right" | "top-left" | "bottom-right" | "bottom-left" |
| `dailyMessageMax` | integer |
| `conversationMessageMax` | integer |
| `sessionTtlMinutes` | integer |
| `issues` Settings for the bug reporter, for… | object |
| `keyFromBrowsers` Let a browser report with the… | boolean |
| `dailyReportMax` How many reports a day this… | integer |
| `escalateAfter` How many more times a known… | integer |
| `antiBot` Make a person's browser solve a… | "pow" |
| `title` The dialog's heading | string |
| `prompt` The line above the box they… | string |
| `thanks` What it says once they have… | string |
| `askEmail` Ask for an address to reply… | boolean |
| `accent` | string |
| `captureCrashes` Catch uncaught errors automatically, as well… | boolean |
| `allowedTools` Narrow the woken turn to these… | string[] |
| `models` Which models this automation may run… | object[] |
| `provider` Which provider serves this work | string |
| `model` Which of its models | string |
| `effort` How hard this model should think,… | string |
| `thinking` Whether this model reasons before it… | boolean |
| `fast` Ask for this model's work at… | boolean |
| `harness` Which agentic loop runs it | "native" | "claude-code" |
| `account` Which account pays for it | string |
| `actsAs` Which persona it speaks as | string |
| `senders` Who may talk to it, and… | object |
| `rules` Walked in order; the first rule… | object[] |
| `label` What to call these people on… | string |
| `ids` Sender ids, as the service names… | string[] |
| `groups` Group ids the service reports on… | string[] |
| `actsAs` Which persona their wakes speak as | string |
| `requireApproval` Hold their wakes for a person,… | boolean |
| `others` What a sender no rule names… | "allow" | "hold" | "ignore" |
| `requireApproval` Hold every fire for a person… | boolean |
| `holdForSeconds` Hold each fire this long before… | number |
| `chore` This automation is a maintenance job,… | boolean |
| `enabled` Whether it fires at all | boolean |
| `runs` | object[] |
| `at` | number |
| `outcome` | "completed" | "skipped" | "error" | "interrupted" |
| `detail` | string |
| `conversationId` | string |
| `nextRun` | number |
| `webhookToken` What a caller presents at /automations/{id}/fire,… | string |
| `ingestKey` What a client with no website… | string |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/automations" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.list();
```

**POST`/automations` Create or edit an automation**

Writes an automation by id. Nothing needs provisioning: the scheduler picks it up on its next sweep.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required The automation's id | string | body |
| `trigger` required What sets it off: a schedule,… | object | body |
| `when kind is "schedule"` | shape | body |
| `cron` required When, in cron notation | string | body |
| `tz` Which clock the times in the… | string | body |
| `afterSessions` Fire only once at least this… | integer | body |
| `when kind is "once"` | shape | body |
| `at` required The moment it fires, in milliseconds | integer | body |
| `when kind is "event"` | shape | body |
| `dailyMax` How many webhook calls a day… | integer | body |
| `when kind is "listener"` | shape | body |
| `provider` required Which service to listen to | string | body |
| `channelId` Narrow it to one channel or… | string | body |
| `eventType` Narrow it to one kind of… | string | body |
| `mentioned` Only when the agent is actually… | boolean | body |
| `branch` Narrow it to one branch, for… | string | body |
| `allowedOrigins` Which websites may reach the public… | string[] | body |
| `when kind is "workspace"` | shape | body |
| `event` required Which happening | "turn.settled" | "agent.landed" | "deps.broken" | "deps.fixed" | body |
| `repo` Narrow it to one repository | string | body |
| `guard` A command run before the wake… | string | body |
| `prompt` required What the woken agent is told | string | body |
| `webchat` Settings for the public chat widget,… | object | body |
| `access` Who may write to it | "public" | "google" | body |
| `requireName` Ask a visitor for a name… | boolean | body |
| `antiBot` How to keep bots out: a… | "turnstile" | "pow" | body |
| `turnstileSiteKey` The public half of those keys,… | string | body |
| `turnstileSecret` The private half, which the sandbox… | string | body |
| `googleClientId` The site's own sign-in client id | string | body |
| `title` | string | body |
| `greeting` | string | body |
| `accent` | string | body |
| `position` | "top-right" | "top-left" | "bottom-right" | "bottom-left" | body |
| `dailyMessageMax` | integer | body |
| `conversationMessageMax` | integer | body |
| `sessionTtlMinutes` | integer | body |
| `issues` Settings for the bug reporter, for… | object | body |
| `keyFromBrowsers` Let a browser report with the… | boolean | body |
| `dailyReportMax` How many reports a day this… | integer | body |
| `escalateAfter` How many more times a known… | integer | body |
| `antiBot` Make a person's browser solve a… | "pow" | body |
| `title` The dialog's heading | string | body |
| `prompt` The line above the box they… | string | body |
| `thanks` What it says once they have… | string | body |
| `askEmail` Ask for an address to reply… | boolean | body |
| `accent` | string | body |
| `captureCrashes` Catch uncaught errors automatically, as well… | boolean | body |
| `allowedTools` Narrow the woken turn to these… | string[] | body |
| `models` required Which models this automation may run… | object[] | body |
| `provider` required Which provider serves this work | string | body |
| `model` required Which of its models | string | body |
| `effort` How hard this model should think,… | string | body |
| `thinking` Whether this model reasons before it… | boolean | body |
| `fast` Ask for this model's work at… | boolean | body |
| `harness` Which agentic loop runs it | "native" | "claude-code" | body |
| `account` Which account pays for it | string | body |
| `actsAs` Which persona it speaks as | string | body |
| `senders` Who may talk to it, and… | object | body |
| `rules` required Walked in order; the first rule… | object[] | body |
| `label` What to call these people on… | string | body |
| `ids` Sender ids, as the service names… | string[] | body |
| `groups` Group ids the service reports on… | string[] | body |
| `actsAs` Which persona their wakes speak as | string | body |
| `requireApproval` Hold their wakes for a person,… | boolean | body |
| `others` required What a sender no rule names… | "allow" | "hold" | "ignore" | body |
| `requireApproval` Hold every fire for a person… | boolean | body |
| `holdForSeconds` Hold each fire this long before… | number | body |
| `chore` This automation is a maintenance job,… | boolean | body |
| `enabled` required Whether it fires at all | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"id":"a1b2c3d4","trigger":{"kind":"schedule","cron":"…","tz":"…","afterSessions":1},"guard":"…","prompt":"Update the changelog for the last five commits.","webchat":{"access":"public","requireName":true,"antiBot":"turnstile","turnstileSiteKey":"…","turnstileSecret":"…","googleClientId":"a1b2c3d4","title":"Update the changelog","greeting":"…","accent":"…","position":"top-right","dailyMessageMax":1,"conversationMessageMax":1,"sessionTtlMinutes":1},"issues":{"keyFromBrowsers":true,"dailyReportMax":1,"escalateAfter":1,"antiBot":"pow","title":"Update the changelog","prompt":"Update the changelog for the last five commits.","thanks":"…","askEmail":true,"accent":"…","captureCrashes":true},"allowedTools":["…","…"],"models":[{"provider":"claude","model":"claude-sonnet-4-6","effort":"…","thinking":true,"fast":true,"harness":"native"},{"provider":"claude","model":"claude-haiku-4-6","effort":"…","thinking":true,"fast":true,"harness":"claude-code"}],"account":"work","actsAs":"…","senders":{"rules":[{"label":"Nightly changelog","ids":["a1b2c3d4","e5f6a7b8"],"groups":["…","…"],"actsAs":"…","requireApproval":true},{"label":"Release notes","ids":["a1b2c3d4","e5f6a7b8"],"groups":["…","…"],"actsAs":"…","requireApproval":true}],"others":"allow"},"requireApproval":true,"holdForSeconds":1,"chore":true,"enabled":true}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.upsert({
 "id": "a1b2c3d4",
 "trigger": {
 "kind": "schedule",
 "cron": "…",
 "tz": "…",
 "afterSessions": 1
 },
 "guard": "…",
 "prompt": "Update the changelog for the last five commits.",
 "webchat": {
 "access": "public",
 "requireName": true,
 "antiBot": "turnstile",
 "turnstileSiteKey": "…",
 "turnstileSecret": "…",
 "googleClientId": "a1b2c3d4",
 "title": "Update the changelog",
 "greeting": "…",
 "accent": "…",
 "position": "top-right",
 "dailyMessageMax": 1,
 "conversationMessageMax": 1,
 "sessionTtlMinutes": 1
 },
 "issues": {
 "keyFromBrowsers": true,
 "dailyReportMax": 1,
 "escalateAfter": 1,
 "antiBot": "pow",
 "title": "Update the changelog",
 "prompt": "Update the changelog for the last five commits.",
 "thanks": "…",
 "askEmail": true,
 "accent": "…",
 "captureCrashes": true
 },
 "allowedTools": [
 "…",
 "…"
 ],
 "models": [
 {
 "provider": "claude",
 "model": "claude-sonnet-4-6",
 "effort": "…",
 "thinking": true,
 "fast": true,
 "harness": "native"
 },
 {
 "provider": "claude",
 "model": "claude-haiku-4-6",
 "effort": "…",
 "thinking": true,
 "fast": true,
 "harness": "claude-code"
 }
 ],
 "account": "work",
 "actsAs": "…",
 "senders": {
 "rules": [
 {
 "label": "Nightly changelog",
 "ids": [
 "a1b2c3d4",
 "e5f6a7b8"
 ],
 "groups": [
 "…",
 "…"
 ],
 "actsAs": "…",
 "requireApproval": true
 },
 {
 "label": "Release notes",
 "ids": [
 "a1b2c3d4",
 "e5f6a7b8"
 ],
 "groups": [
 "…",
 "…"
 ],
 "actsAs": "…",
 "requireApproval": true
 }
 ],
 "others": "allow"
 },
 "requireApproval": true,
 "holdForSeconds": 1,
 "chore": true,
 "enabled": true
});
```

**GET`/automations/catalog` What can trigger an automation here**

Every trigger this sandbox understands and every template worth starting from, the daemon's own merged with each installed extension's. Writing an automation is checked against this same list, so a screen and the daemon can never disagree about what is allowed.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `sources` | object[] |
| `provider` | string |
| `label` | string |
| `logo` | string |
| `icon` | string |
| `events` | object[] |
| `value` | string |
| `label` | string |
| `channel` | object |
| `label` | string |
| `placeholder` | string |
| `hint` | string |
| `branchField` | object |
| `label` | string |
| `placeholder` | string |
| `hint` | string |
| `sender` | object |
| `label` | string |
| `placeholder` | string |
| `hint` | string |
| `senderGroup` | object |
| `label` | string |
| `placeholder` | string |
| `hint` | string |
| `mentionLabel` | string |
| `starterPrompt` | string |
| `requires` | string[] |
| `enabled` | boolean |
| `templates` | object[] |
| `id` | string |
| `title` | string |
| `logo` | string |
| `icon` | string |
| `requires` | string[] |
| `trigger` | object |
| `when kind is "schedule"` | shape |
| `cron` When, in cron notation | string |
| `tz` Which clock the times in the… | string |
| `afterSessions` Fire only once at least this… | integer |
| `when kind is "once"` | shape |
| `at` The moment it fires, in milliseconds | integer |
| `when kind is "event"` | shape |
| `dailyMax` How many webhook calls a day… | integer |
| `when kind is "listener"` | shape |
| `provider` Which service to listen to | string |
| `channelId` Narrow it to one channel or… | string |
| `eventType` Narrow it to one kind of… | string |
| `mentioned` Only when the agent is actually… | boolean |
| `branch` Narrow it to one branch, for… | string |
| `allowedOrigins` Which websites may reach the public… | string[] |
| `when kind is "workspace"` | shape |
| `event` Which happening | "turn.settled" | "agent.landed" | "deps.broken" | "deps.fixed" |
| `repo` Narrow it to one repository | string |
| `guard` | string |
| `holdForSeconds` | integer |
| `prompt` | string |
| `note` | string |
| `setup` | string |
| `description` | string |
| `offer` | "create" | "configure" |
| `chore` | boolean |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/automations/catalog" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.catalog();
```

**POST`/automations/{id}/enabled` Turn an automation on or off**

Flips only the switch, so a row in a list can be toggled without rebuilding the whole record.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required | string | address |
| `enabled` required | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations/a1b2c3d4/enabled" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"enabled":true}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.setEnabled({
 "id": "a1b2c3d4",
 "enabled": true
});
```

**DELETE`/automations/{id}` Delete an automation**

Removes it, so nothing fires from it again.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X DELETE "$SANDBOX/automations/a1b2c3d4" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.remove({
 "id": "a1b2c3d4"
});
```

**POST`/automations/{id}/rotate-token` Rotate an automation's webhook token or intake key**

Mints a new credential for the door this automation opens and retires the old one at once. Every caller has to be handed the new URL; that is the point. Refused for an automation with no door.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `token` The freshly minted credential | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations/a1b2c3d4/rotate-token" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.rotateToken({
 "id": "a1b2c3d4"
});
```

**POST`/automations/{id}/run` Fire an automation by hand**

The answer to writing something that runs at three in the morning and having no way to try it. It takes exactly the path the real trigger takes, including the check that decides whether there was anything to do, since skipped by the guard is the most useful thing this can tell you. A switched-off automation fires too, because trying it before switching it on is the main reason to press this. Not available for the trigger that listens for incoming messages, where a hand-fire would produce an agent asked to handle events and handed none; send the bot a message instead. Answers straight away and runs detached.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations/a1b2c3d4/run" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.run({
 "id": "a1b2c3d4"
});
```

**GET`/automations/senders/{provider}` Who has written to a listener source**

Everyone whose message reached one of this source's automations, newest first, admitted or not. What the sender rules picker offers by name while storing the id the service vouches for.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `provider` required Which listener source | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `senders` Newest first | object[] |
| `id` The sender id the service vouches… | string |
| `name` What they were called on their… | string |
| `groups` The group ids the service reported… | string[] |
| `firstSeenAt` When they first reached an automation… | number |
| `lastSeenAt` When they last did, in milliseconds | number |
| `messages` How many of their messages reached… | number |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/automations/senders/claude" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.senders({
 "provider": "claude"
});
```

**GET`/automations/pending` Automations waiting for a yes**

The queue an automation set to ask first lands in each time it would have fired.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `approvals` Everything waiting for a yes | object[] |
| `id` This waiting item's own id, which… | string |
| `automationId` Which automation it came from | string |
| `payload` What set it off, kept whole… | string |
| `origin` Where the message came from, kept… | object |
| `automationId` | string |
| `provider` | string |
| `channelId` | string |
| `author` | string |
| `title` What the conversation would be called | string |
| `conversationId` The thread this belongs to, when… | string |
| `sessionId` The provider session that thread last… | string |
| `thread` Which inbound thread this belongs to,… | string |
| `actsAs` Which persona the approved run speaks… | string |
| `createdAt` When it started waiting, in milliseconds | number |
| `autoRunAt` When it goes ahead on its… | number |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/automations/pending" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.pendingList();
```

**POST`/automations/pending/{id}/approve` Let a held automation run**

Releases one waiting automation and runs the wake it was holding. Answers straight away and runs detached.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which waiting item | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations/pending/a1b2c3d4/approve" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.approve({
 "id": "a1b2c3d4"
});
```

**POST`/automations/pending/{id}/reject` Drop a held automation**

Throws one waiting fire away. The automation stays on, and the next trigger queues as usual.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which waiting item | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/automations/pending/a1b2c3d4/reject" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.automations.reject({
 "id": "a1b2c3d4"
});
```

More in Agents

[Previous ← Loops](https://intentic.dev/api/loops/)
