# Custom commands

> Build custom ChatOps commands for Dailybot: text commands, in-chat forms, and HTTP commands with dynamic responses.

Language: en
Canonical: https://www.dailybot.com/developers/custom-commands
Markdown: send header `Accept: text/markdown` on any URL to receive Markdown instead of HTML.
Last Updated: 2026-04-06

---

# Custom commands

Custom commands let you extend Dailybot with your own ChatOps interactions. Users trigger commands by typing a keyword in chat, and Dailybot responds with text, forms, or dynamic content from your endpoints.

## Command types

Dailybot supports three types of custom commands:

- **Text Commands** — Return a predefined text response
- **In-Chat Form Commands** — Trigger native forms that collect data
- **HTTP Commands** — Send requests to your endpoints for dynamic responses

## Text commands

Text commands return a simple, predefined response. They are useful for frequently accessed information like company values, on-call schedules, or quick reference links.

## In-chat form commands

In-chat form commands trigger native Dailybot forms that collect structured data. Responses are stored in Dailybot tables. Users can search through collected responses by typing the command name followed by "search" and a query term.

## HTTP commands

HTTP commands are the most powerful type. When a user triggers the command, Dailybot sends a POST request to your endpoint with context about the user and command, and your endpoint returns the response to display in chat.

> **HTTPS required:** Your endpoint **must** use HTTPS. Dailybot will not send requests to HTTP endpoints.

### Authentication header

Dailybot sends an `X-Dailybot-Signature` header with every request. This contains the command signature so your endpoint can verify the request came from Dailybot.

### Request payload

The POST body includes the following context fields:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `intent` | string | Yes | The command intent name as configured in Dailybot. |
| `event_timestamp` | string | Yes | ISO 8601 timestamp of when the command was triggered. |
| `organization_uuid` | string | Yes | UUID of the organization. |
| `user_uuid` | string | Yes | UUID of the user who triggered the command. |
| `user_full_name` | string | Yes | Full name of the triggering user. |
| `user_role` | string | Yes | Role of the user (admin, member, etc.). |
| `is_channel_message` | boolean | Yes | Whether the command was triggered in a channel (true) or direct message (false). |
| `platform` | string | Yes | Chat platform (slack, msteams, google_chat, etc.). |
| `params.query` | string | No | Additional text passed after the command name. |

```json
{
  "intent": "deploy",
  "event_timestamp": "2026-02-14T12:00:00Z",
  "organization_uuid": "org-1234-abcd",
  "user_uuid": "usr-5678-efgh",
  "user_full_name": "Jane Smith",
  "user_role": "admin",
  "is_channel_message": true,
  "platform": "slack",
  "params": {
    "query": "production v2.1.0"
  }
}
```

> **Tip:** Use `params.query` to build flexible commands. Users can append parameters after the command name (e.g., `/deploy production v2.1.0`), and the extra text becomes the query string.

### Response formats

#### Plain text

The simplest response: return a text body as a valid JSON string. Dailybot will display it directly in chat.

```json
"Deployment started for production v2.1.0 ✅"
```

#### JSON field

Return a JSON object and specify which field to render as the response in your command settings.

```json
{
  "status": "success",
  "message": "Deployment started for production v2.1.0",
  "build_id": "build-789"
}
```

#### Interactive buttons

Return a JSON object with a message, optional image, and an array of buttons for interactive workflows.

Button fields:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `label` | string | Yes | Visible text on the button. |
| `label_after_click` | string | Yes | Text shown after the button is clicked. |
| `value` | string | Yes | Must include the command intent name. Additional text becomes `params.query`. |
| `button_type` | string | Yes | Must be `"Command"`. |

```json
{
  "message": "Choose an environment to deploy:",
  "buttons": [
    {
      "label": "Production",
      "label_after_click": "Deploying to production...",
      "value": "deploy production",
      "button_type": "Command"
    },
    {
      "label": "Staging",
      "label_after_click": "Deploying to staging...",
      "value": "deploy staging",
      "button_type": "Command"
    }
  ]
}
```

### Response timeout

> **10-second timeout:** Your endpoint must respond within **10 seconds**. If your operation takes longer, [contact the Dailybot support team](https://app.dailybot.com/forms/86a5b53f-8bc9-4b84-b78f-7c51b805d674/responses/create) to discuss asynchronous response options.

## Code example

Dailybot provides a [CodeSandbox example](https://codesandbox.io/s/dailybot-sample-command-demo-6nu1u) demonstrating a Node.js implementation of an HTTP command endpoint.

## Best practices

- Always validate the `X-Dailybot-Signature` header to verify requests
- Use `params.query` for flexible, multi-purpose commands
- Keep responses under 10 seconds — offload heavy processing to background jobs
- Use interactive buttons to build multi-step workflows
- Return helpful error messages when inputs are invalid
- Log requests for debugging — include the `user_uuid` for tracing

---

## 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)
- [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) (this page)
- [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)

