# Automations

> Create, manage, trigger, and monitor automated workflows — including api_trigger firing via API or interactive buttons.

Language: en
Canonical: https://www.dailybot.com/developers/api/workflows
Markdown: send header `Accept: text/markdown` on any URL to receive Markdown instead of HTML.
Last Updated: 2026-07-23

---

# Workflows

Create, manage, trigger, and monitor automated workflows and execution logs.

> **CLI vs API key:** CLI tokens are **read-only** for workflow create, update, and delete — those writes require `X-API-KEY`. **Trigger** is the exception: it accepts an API key **or** a CLI token with write capability. All workflow endpoints are **plan-gated**; organizations without the workflows feature may receive `403` even on reads.

## Endpoints summary

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/workflows/` | List all workflows |
| GET | `/v1/workflows/{uuid}/` | Get a specific workflow |
| POST | `/v1/workflows/` | Create a workflow |
| PUT | `/v1/workflows/{uuid}/` | Replace a workflow |
| PATCH | `/v1/workflows/{uuid}/` | Update a workflow |
| DELETE | `/v1/workflows/{uuid}/` | Delete a workflow |
| POST | `/v1/workflows/{uuid}/trigger/` | Trigger an active `api_trigger` workflow |
| GET | `/v1/workflows/{uuid}/execution_logs/` | Get workflow execution logs |
| POST | `/v1/workflows/{uuid}/duplicate/` | Duplicate a workflow |

---

## GET /v1/workflows/

Returns all workflows in the organization. Paginated with the standard envelope `{ count, next, previous, results }`.

### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `is_active` | boolean | No | Filter by active status. |
| `search` | string | No | Case-insensitive substring match on the workflow `name` field. Max 256 chars. Over-length returns `400 search_query_too_long`. |
| `start_date` | string (`YYYY-MM-DD`) | No | Filter workflows created on or after this date (caller's timezone). Also accepted: `date_start`, `date_from`. |
| `end_date` | string (`YYYY-MM-DD`) | No | Filter workflows created on or before this date (caller's timezone). Also accepted: `date_end`, `date_to`. Inverted ranges return `400 invalid_date_range`. |
| `page` | integer | No | Page number (1-indexed). Default: 1. |
| `page_size` | integer | No | Items per page (max 100). Default: 25. Alias: `limit`. |
| `offset` | integer | No | Offset-based pagination (accepted for backward compatibility). |

```bash
curl -X GET "https://api.dailybot.com/v1/workflows/?search=onboarding&start_date=2026-06-01&end_date=2026-06-30&page_size=50" \
  -H "X-API-KEY: your_api_key"
```

**Response (200 OK):**

```json
{
  "count": 5,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "wf-uuid",
      "name": "New Hire Onboarding",
      "is_active": true,
      "trigger_type": "event",
      "created_at": "2026-01-15T00:00:00Z"
    }
  ]
}
```

> **Identifier:** Each workflow uses `id` as its identifier — the value is a UUID (see [Identifiers](/developers/conventions#identifiers)).

---

## GET /v1/workflows/{uuid}/

Returns a specific workflow with full configuration.

```bash
curl -X GET "https://api.dailybot.com/v1/workflows/wf-uuid/" \
  -H "X-API-KEY: your_api_key"
```

**Response (200 OK):**

```json
{
  "uuid": "wf-uuid",
  "name": "New Hire Onboarding",
  "is_active": true,
  "trigger_type": "event",
  "trigger_config": {
    "event": "organization.user_activated"
  },
  "actions": [
    {
      "type": "send_message",
      "target_type": "user",
      "message": "Welcome to the team! Here's what to do first..."
    }
  ],
  "created_at": "2026-01-15T00:00:00Z"
}
```

---

## POST /v1/workflows/

Creates a new workflow. **Auth: API key only** — CLI tokens are rejected on `POST`.

### Body parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `name` | string | Yes | Workflow name. |
| `is_active` | boolean | No | Whether the workflow is active. Default: `true`. |
| `trigger_type` | string | Yes | Trigger type. Use `api_trigger` for workflows fired via this API or interactive buttons (selectable in the automations builder as **When triggered via API or button**). Other built-in types include `event`, `schedule`, and `manual`. |
| `trigger_config` | object | Yes | Trigger configuration (depends on `trigger_type`). |
| `actions` | array of objects | Yes | List of actions to execute. |

```bash
curl -X POST "https://api.dailybot.com/v1/workflows/" \
  -H "X-API-KEY: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Deploy Notification",
    "trigger_type": "api_trigger",
    "trigger_config": {},
    "actions": [
      {
        "type": "send_message",
        "target_type": "channel",
        "target_uuid": "channel-uuid",
        "message": "Deployment complete: {{trigger.body.service}} v{{trigger.body.version}}"
      }
    ]
  }'
```

**Response (201 Created):**

```json
{
  "uuid": "wf-new-uuid",
  "name": "Deploy Notification",
  "is_active": true,
  "trigger_type": "api_trigger",
  "created_at": "2026-04-06T10:00:00Z"
}
```

---

## DELETE /v1/workflows/{uuid}/

Deletes a workflow.

```bash
curl -X DELETE "https://api.dailybot.com/v1/workflows/wf-uuid/" \
  -H "X-API-KEY: your_api_key"
```

**Response (204 No Content)**

---

## POST /v1/workflows/{uuid}/trigger/

Manually fires a workflow whose trigger type is **`api_trigger`** — the trigger purpose-built for external firing. Workflows with any other trigger type (scheduled, form/check-in events, commands, …) keep their own firing paths and return `400 workflow_not_triggerable`.

**Auth:** API key or CLI token with write capability.
**Permissions:** plan gate + org membership; per-workflow execution permission is enforced.

### Request body

Body is optional:

```json
{"payload": {"env": "production", "requested_by": "release-bot"}}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `payload` | object | No | Free-form JSON object, max 8 KiB when serialized. Exposed to workflow steps as `{{trigger.body.*}}` variables. |

```bash
curl -X POST "https://api.dailybot.com/v1/workflows/wf-uuid/trigger/" \
  -H "X-API-KEY: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"payload": {"env": "production"}}'
```

**Response — `202 Accepted`** (the run is queued, not executed inline):

```json
{"detail": "Workflow trigger accepted.", "workflow_uuid": "wf-uuid", "queued": true}
```

### Error codes

| Status | `code` | When |
|--------|--------|------|
| `400` | `workflow_not_triggerable` | Trigger type is not `api_trigger`, or the workflow is inactive. |
| `400` | `workflow_trigger_payload_invalid` | `payload` is not an object or serializes to > 8 KiB. |
| `403` | `workflow_execute_not_allowed` | Caller lacks execute permission on this workflow. |
| `409` | `workflow_frozen` | The workflow is frozen (plan/limit state). |
| `404` | — | Unknown UUID or out of the caller's organization. |
| `401` | — | Missing, invalid, or expired credential. |
| `429` | — | Throttled — respect the `Retry-After` header. |

The same `api_trigger` workflows can also be fired from an interactive message button via `buttons[].callback_workflow` (optionally with a `modal_body` whose submitted fields arrive as `{{trigger.fields.<name>}}`). See [Bot messaging](/developers/api/messaging) for button fields.

Fired via the public API, `{{trigger.source}}` is `"api"` and the button/field keys are null or empty.

---

## Trigger variables

Workflow steps can reference the firing context through the `{{trigger.*}}` namespace:

| Variable | Description |
|----------|-------------|
| `{{trigger.source}}` | How the workflow was fired: `api`, `button_click`, or `modal_submit`. |
| `{{trigger.body.*}}` | Keys from the optional API `payload` object (e.g. `{{trigger.body.env}}`). |
| `{{trigger.button_id}}` | Server-minted button id (`$btn/<uuid4>`) when fired from a message button. |
| `{{trigger.button_value}}` | The clicked button's `value` string — use for branching when several buttons point at the same workflow. |
| `{{trigger.fields.<name>}}` | Modal input values when fired via `modal_body` + `callback_workflow` (e.g. `{{trigger.fields.summary}}`). |
| `{{trigger.clicked_at}}` | ISO 8601 timestamp of the click or modal submit. |
| `{{trigger.user.uuid}}` | UUID of the user who fired the workflow (clicker or API caller). |
| `{{trigger.user.full_name}}` | Full display name of the firing user. |
| `{{trigger.user.first_name}}` | First name of the firing user. |
| `{{trigger.user.email}}` | Email of the firing user. |
| `{{trigger.user.role}}` | Role: `ADMIN_ORG`, `ADMIN`, `MANAGER`, `MEMBER`, or `GUEST`. |
| `{{trigger.triggered_by_user_uuid}}` | UUID of the user who triggered the workflow (alias of `{{trigger.user.uuid}}` for button/modal paths). |

---

## Recipes

### Modal → Workflow

Compose `modal_body` with `callback_workflow` on an interactive button: the click opens the modal, and on submit the field values are delivered to the workflow as `{{trigger.fields.<input.name>}}` — no external server involved.

```bash
curl -X POST "https://api.dailybot.com/v1/send-message/" \
  -H "X-API-KEY: $DAILYBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Report an incident:",
    "target_users": ["user-uuid"],
    "buttons": [
      {
        "label": "Report",
        "button_type": "interactive",
        "value": "report",
        "callback_workflow": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "modal_body": {
          "title": "New incident",
          "blocks": [
            {
              "type": "input",
              "name": "summary",
              "label": "What happened?",
              "multiline": true,
              "required": true
            }
          ]
        }
      }
    ]
  }'
```

The workflow (trigger type `api_trigger`) can then use `{{trigger.fields.summary}}` in any step — pre-fill a form answer, compose a message, or feed an AI prompt. A modal with `input` blocks and neither `callback_url` nor `callback_workflow` is rejected (`input_without_callback`).

### Value-branching — several buttons, one workflow

Point multiple buttons at the **same** workflow UUID with different `value` strings, then branch inside the workflow on `{{trigger.button_value}}`:

```bash
curl -X POST "https://api.dailybot.com/v1/send-message/" \
  -H "X-API-KEY: $DAILYBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Deploy is ready — choose an action:",
    "target_users": ["user-uuid"],
    "buttons": [
      {
        "label": "Deploy to staging",
        "button_type": "interactive",
        "value": "staging",
        "callback_workflow": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      },
      {
        "label": "Deploy to production",
        "button_type": "interactive",
        "value": "production",
        "callback_workflow": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      },
      {
        "label": "Cancel",
        "button_type": "interactive",
        "value": "cancel",
        "callback_workflow": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      }
    ]
  }'
```

Inside the workflow, a conditional step on `{{trigger.button_value}}` routes `staging`, `production`, or `cancel` without maintaining three separate workflow definitions.

For the full button schema (`label`, `modal_body`, `response`, and more), see [Bot messaging](/developers/api/messaging).

---

## GET /v1/workflows/{uuid}/execution_logs/

Returns execution logs for a specific workflow.

### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `date_start` | string | No | Start date (YYYY-MM-DD). |
| `date_end` | string | No | End date (YYYY-MM-DD). |
| `status` | string | No | Filter by status: `success`, `failure`, or `pending`. |
| `limit` | integer | No | Number of results. Default: 50. |

```bash
curl -X GET "https://api.dailybot.com/v1/workflows/wf-uuid/execution_logs/?limit=10" \
  -H "X-API-KEY: your_api_key"
```

**Response (200 OK):**

```json
{
  "count": 25,
  "results": [
    {
      "id": "log-uuid",
      "workflow_uuid": "wf-uuid",
      "status": "success",
      "trigger_data": { "source": "api" },
      "executed_at": "2026-04-06T09:00:00Z",
      "duration_ms": 145
    }
  ]
}
```

---

## POST /v1/workflows/{uuid}/duplicate/

Duplicates a workflow with a new name.

```bash
curl -X POST "https://api.dailybot.com/v1/workflows/wf-uuid/duplicate/" \
  -H "X-API-KEY: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Deploy Notification (Copy)"}'
```

**Response (201 Created):**

```json
{
  "uuid": "wf-copy-uuid",
  "name": "Deploy Notification (Copy)",
  "is_active": false,
  "created_at": "2026-04-06T10:05:00Z"
}
```

## Endpoints in this group

Manage automation workflows. Creating, updating, and deleting workflows is API-key only — CLI tokens are read-only. Plan-gated.

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/workflows/` | List workflows (plan-gated) |
| POST | `/v1/workflows/` | Create a workflow (API-Key only) |
| GET | `/v1/workflows/{uuid}/` | Retrieve a workflow |
| PATCH | `/v1/workflows/{uuid}/` | Update a workflow (API-Key only) |
| DELETE | `/v1/workflows/{uuid}/` | Delete a workflow (API-Key only) |
| POST | `/v1/workflows/{uuid}/trigger/` | Trigger an active api_trigger workflow |

### GET `/v1/workflows/`

**List workflows (plan-gated)**

Paginated list of workflows the caller can access. Returns the standard envelope ({count, next, previous, results}). Supports search by name and date-range filters.

- **Auth:** API key (`X-API-KEY`), CLI Bearer (read)
- **Rate limit:** `default`
- **Pagination:** Page-number pagination

#### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `search` | string | No | Case-insensitive substring search on workflow name. Max 256 chars. |
| `start_date` | string (YYYY-MM-DD) | No | Inclusive start date (caller's timezone). Also accepted: date_start, date_from. |
| `end_date` | string (YYYY-MM-DD) | No | Inclusive end date, 23:59:59 in caller's timezone. Also accepted: date_end, date_to. |
| `page` | integer | No | Page number (1-indexed). Default: 1. |
| `page_size` | integer | No | Items per page. Default: 25, max: 100. Alias: limit. |
| `offset` | integer | No | Offset-based pagination (accepted for backward compatibility). |

#### Response body

```json
{
  "count": "integer",
  "next": "string|null",
  "previous": "string|null",
  "results": "array<{ id, name, description, is_active, created_at, updated_at, ... }>"
}
```

#### Error codes

| Status | When |
|--------|------|
| `400` | Validation error (search_query_too_long, invalid_date_range) |
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled - Retry-After header set |

#### Example (curl)

```bash
curl -sS -X GET 'https://api.dailybot.com/v1/workflows/?page=1&page_size=25' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

#### Notes

- Requires workflows plan tier.

### POST `/v1/workflows/`

**Create a workflow (API-Key only)**

Create a workflow (API-Key only)

- **Auth:** API key (`X-API-KEY`)
- **Rate limit:** `default`
- **Pagination:** No pagination

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled - Retry-After header set |
| `400` | Validation error |

#### Example (curl)

```bash
curl -sS -X POST 'https://api.dailybot.com/v1/workflows/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

#### Notes

- CLI token is rejected on POST.

### GET `/v1/workflows/{uuid}/`

**Retrieve a workflow**

Retrieve a workflow

- **Auth:** API key (`X-API-KEY`), CLI Bearer (read)
- **Rate limit:** `default`
- **Pagination:** No pagination

#### Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `uuid` | string (uuid) | Yes | — |

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled - Retry-After header set |
| `404` | Not found or not visible |

#### Example (curl)

```bash
curl -sS -X GET 'https://api.dailybot.com/v1/workflows/{uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### PATCH `/v1/workflows/{uuid}/`

**Update a workflow (API-Key only)**

Update a workflow (API-Key only)

- **Auth:** API key (`X-API-KEY`)
- **Rate limit:** `default`
- **Pagination:** No pagination

#### Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `uuid` | string (uuid) | Yes | — |

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled - Retry-After header set |
| `400` | Validation error |
| `404` | Not found or not visible |

#### Example (curl)

```bash
curl -sS -X PATCH 'https://api.dailybot.com/v1/workflows/{uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### DELETE `/v1/workflows/{uuid}/`

**Delete a workflow (API-Key only)**

Delete a workflow (API-Key only)

- **Auth:** API key (`X-API-KEY`)
- **Rate limit:** `default`
- **Pagination:** No pagination

#### Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `uuid` | string (uuid) | Yes | — |

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled - Retry-After header set |
| `404` | Not found or not visible |

#### Example (curl)

```bash
curl -sS -X DELETE 'https://api.dailybot.com/v1/workflows/{uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### POST `/v1/workflows/{uuid}/trigger/`

**Trigger an active api_trigger workflow**

Manually fires a workflow whose trigger type is api_trigger. The run is queued asynchronously (202 Accepted). An optional payload JSON object (≤ 8 KiB) is exposed to workflow steps as trigger context.

- **Auth:** API key (`X-API-KEY`), CLI Bearer (write)
- **Rate limit:** `default`
- **Pagination:** No pagination

#### Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `uuid` | string (uuid) | Yes | — |

#### Request body

```json
{
  "payload": "object (optional) — free-form JSON object, max 8 KiB when serialized. Exposed to workflow steps as {{trigger.body.*}} variables."
}
```

#### Response body

```json
{
  "detail": "string — human-readable acceptance message",
  "workflow_uuid": "string (uuid) — the triggered workflow",
  "queued": "boolean — always true on 202; the run is queued, not executed inline"
}
```

#### Error codes

| Status | When |
|--------|------|
| `400` | workflow_not_triggerable — trigger type is not api_trigger, or the workflow is inactive |
| `400` | workflow_trigger_payload_invalid — payload is not a JSON object or serializes to > 8 KiB |
| `401` | Missing, invalid, or expired credential |
| `403` | workflow_execute_not_allowed — caller lacks execute permission on this workflow; or plan feature gate denies workflows |
| `404` | Unknown UUID or workflow outside the caller's organization |
| `409` | workflow_frozen — the workflow is frozen (plan/limit state) |
| `429` | Throttled — Retry-After header set |

#### Example (curl)

```bash
curl -sS -X POST 'https://api.dailybot.com/v1/workflows/{uuid}/trigger/' \
  -H 'X-API-KEY: $DAILYBOT_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"payload": {"env": "production", "requested_by": "release-bot"}}'
```

#### Notes

- Plan-gated: organizations without the workflows feature receive 403 on every workflow endpoint, including trigger.
- Only workflows with trigger type api_trigger can be fired via this endpoint. Other trigger types (scheduled, form/check-in events, commands, …) keep their own firing paths.
- The same api_trigger workflows can also be fired from an interactive message button via buttons[].callback_workflow (optionally with modal_body whose submitted fields arrive as {{trigger.fields.<name>}}).
- Trigger variables available to steps: {{trigger.source}}, {{trigger.body.*}}, {{trigger.button_id}}, {{trigger.button_value}}, {{trigger.fields.<name>}}, {{trigger.clicked_at}}, {{trigger.user.*}}, {{trigger.triggered_by_user_uuid}}.
- Unlike create/update/delete, trigger accepts CLI tokens with write capability — API key or CLI write both work.

---

## Developer portal navigation

**Getting Started**

- [Overview](/developers)
- [Quick start](/developers/getting-started)
- [Authentication](/developers/authentication)

**API Reference**

- [API Overview](/developers/api)
- [Users](/developers/api/users)
- [Organization](/developers/api/organization)
- [Teams](/developers/api/teams)
- [Invitations](/developers/api/invitations)
- [Check-ins](/developers/api/check-ins)
- [Forms](/developers/api/forms)
- [Report channels](/developers/api/report-channels)
- [Templates](/developers/api/templates)
- [Kudos](/developers/api/kudos)
- [Mood tracking](/developers/api/mood)
- [Important dates](/developers/api/important-dates)
- [Messaging](/developers/api/messaging)
- [Automations](/developers/api/workflows) (this page)
- [Webhooks](/developers/api/webhooks)
- [Commands platform](/developers/api/commands-platform)
- [Agents](/developers/api/agents)
- [OAuth2](/developers/api/oauth2)
- [Integrations](/developers/api/integrations)
- [CLI](/developers/api/cli)

**API guides**

- [Errors & Status Codes](/developers/errors)
- [Rate Limits](/developers/rate-limits)
- [Conventions](/developers/conventions)
- [API Changelog](/developers/api-changelog)
- [Recipes](/developers/recipes)

**Developer Features**

- [Custom commands](/developers/custom-commands)
- [Serverless commands](/developers/serverless)
- [Webhooks & events](/developers/webhooks)
- [Automation API trigger](/developers/workflow-trigger)
- [Activity API](/developers/activity-api)

**CLI**

- [Overview](/developers/cli)
- [Authentication](/developers/cli-authentication)
- [Command reference](/developers/cli-reference)
- [CI/CD recipes](/developers/cli-ci-cd)
- [Configuration](/developers/cli-configuration)
- [Troubleshooting](/developers/cli-troubleshooting)

**Agent Skill**

- [Overview](/developers/agent-skill)
- [Skills catalog](/skills)

---

## Site navigation

**Product:**
- [Home](/)
- [Product](/product)
- [Pricing](/pricing)
- [Enterprise](/enterprise)
- [Integrations](/integrations)
- [Templates](/templates)

**Resources:**
- [Blog](/blog)
- [Academy](/academy)
- [Changelog](/changelog)
- [Help Center](/help)
- [Developers](/developers)
- [Agents](/agents)

**Company:**
- [About](/about)
- [Careers](/careers)
- [Security](/security)
- [Contact Sales](/demo)

**Connect:**
- [LinkedIn](https://www.linkedin.com/company/dailybot/)
- [X/Twitter](https://twitter.com/dailybot)
- [GitHub](https://github.com/Dailybot-Inc)
- [YouTube](https://www.youtube.com/channel/UC3uM9V52vwX7e3vQpCc4qvA)

