# Forms

> Programmatic access to Dailybot forms — list, filter, sort, search, submit responses with automation or anonymous modes, attach guest identities, transition through workflow states, and manage approval flows.

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

---

## Forms

Programmatic access to Dailybot forms — list, filter, sort, search, submit responses with automation or anonymous modes, attach guest identities, transition through workflow states, and manage approval flows.

See the full endpoint reference — with parameters, request/response schemas, error codes, and code samples — at the interactive page: [/developers/api/forms](/developers/api/forms).

Every endpoint in this group accepts either an API key (`X-API-KEY`) or a CLI Bearer token (`Authorization: Bearer …`) unless explicitly marked otherwise, per the auth method matrix at [/developers/authentication#parity-matrix](/developers/authentication#parity-matrix).

### Identifier

The Form and Form Response resources use a dedicated `uuid` field (RFC 4122 v4) as the canonical identifier in every request and response. Path parameters like `/v1/forms/{uuid}/responses/{response_uuid}/` also use the `uuid` value.

### Pagination

All list endpoints return the standard pagination envelope:

```json
{
  "count": 42,
  "next": "https://api.dailybot.com/v1/forms/?offset=25&limit=25",
  "previous": null,
  "results": [...]
}
```

| Parameter | Type | Default | Max | Description |
|-----------|------|---------|-----|-------------|
| `offset` | integer | 0 | — | Pagination offset |
| `limit` | integer | 25 | 50 | Page size |

See [/developers/conventions#pagination](/developers/conventions#pagination) for the full spec.

### Listing forms

`GET /v1/forms/` returns every form in the caller's organization (archived excluded by default). Capabilities — editing, response visibility, state changes — are governed by the form's permissions; owner and org admins always have full access.

Supports filtering by scope, owner, searching by name, sorting, and date ranges.

**Scope filters** (`?filter=`):

| Value | Description |
|-------|-------------|
| `all` | All org forms (default) |
| `public` | Only forms with privacy = EVERYONE |
| `approval` | Only forms with approval flow enabled |
| `workflow` | Only forms with workflow states enabled |
| `archived` | Only archived forms |
| `me` | **Deprecated** — use `owner_user_ids` with your own UUID instead. Still works for backward compatibility. |

**Owner filter** (`?owner_user_ids=`): Comma-separated user UUIDs (max 50). Returns only forms owned by those users. ANDs with every other parameter (`search`, `filter`, pagination, ordering). Cross-org UUIDs never match (returns 0 rows, not an error). Replaces the deprecated `filter=me`.

**Sorting** (`?order=`):

| Value | Description |
|-------|-------------|
| `recent` | By creation date, newest first (default) |
| `alphabetical` | By form name |
| `total` | By total number of responses |

Use `?is_ascend=true` to reverse the sort direction.

```bash
# Workflow forms, sorted alphabetically ascending
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/?filter=workflow&order=alphabetical&is_ascend=true"

# Search by name
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/?search=Access%20Request"

# Forms sorted by most responses
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/?order=total"
```

**Including questions** — pass `?include=questions` to embed each form's questions inline:

```json
{
  "uuid": "...",
  "name": "Sprint Review",
  "questions": [
    {
      "uuid": "q-uuid-1",
      "label": "What did you accomplish?",
      "type": "text",
      "required": true,
      "options": null
    }
  ]
}
```

### Discovering form owners

`GET /v1/forms/form-owners/` returns a paginated, searchable list of org members who own at least one non-archived form. Only active, approved members appear. Ordered by `full_name` ascending.

Designed for UI pickers: a 1000-member org returns only its (typically few) form owners, not the whole member directory.

| Parameter | Type | Default | Max | Description |
|-----------|------|---------|-----|-------------|
| `search` | string | — | — | Case-insensitive search on name and email |
| `offset` | integer | 0 | — | Pagination offset |
| `limit` | integer | 20 | 50 | Page size |

Each result contains `uuid`, `full_name`, `image`, and `role` (org role slug: `ADMIN_ORG`, `MANAGER`, `ADMIN`, `MEMBER`, `GUEST`).

**Email visibility:** the `email` field appears only when the caller has email visibility — org admins, managers, and team admins. Member-scoped callers receive rows without the `email` key (omitted entirely, never `null`). API keys inherit the key owner's role. The `search` parameter still matches on email server-side for every caller, but the value is never echoed back to callers without visibility. Integrators must not assume `email` is present on picker rows.

```bash
# Search form owners by name
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/form-owners/?search=serg&limit=20"

# Filter forms list by owner
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/?owner_user_ids=<uuid-1>,<uuid-2>"
```

**Deprecated fields:**

- `available_on_list_view` — still accepted on `POST /v1/forms/create/` and `PATCH /v1/forms/{uuid}/config/` but is a server-side no-op. List visibility is now org-wide. To hide a form, archive it.
- `filter=me` — still works for backward compatibility but is deprecated. Use `owner_user_ids` with your own user UUID instead. When both are sent, they intersect. The `me` scoping on form **responses** endpoints is unrelated and not deprecated.

Both deprecated fields remain accepted indefinitely; removal (and the eventual column drop) will be announced as a separate changelog entry with its own migration window. Integrators should migrate now but nothing breaks on deploy day.

**Migration note for integrators:** replace `filter=me` with `owner_user_ids=<your-uuid>`. Clients that relied on `available_on_list_view` to hide forms must now filter client-side or archive the form.

### Listing form responses

`GET /v1/forms/{uuid}/responses/` returns the caller's own responses by default. Pass `?all=true` or any advanced filter to see all responses (requires VIEW_REPORTS permission on the form).

**Permission model:**

| Scenario | Required permission |
|----------|-------------------|
| Own responses only (default) | Any authenticated user with form access |
| `all=true` or `submission_sources`, `submitter_user_ids`, `flow_status` | VIEW_REPORTS on the form |

**Submission source filter** (`?submission_sources=`):

Every response belongs to exactly one of these four mutually exclusive categories:

| Value | Description |
|-------|-------------|
| `member` | Normal identified org member submission |
| `anonymous` | Org member on an anonymous form (identity hidden) |
| `automation` | Submitted via API/CLI with automation flag |
| `public` | Submitted via the public form URL by an external guest |

Comma-separated values use OR semantics: `?submission_sources=automation,public` returns automation OR public responses.

**Approval flow filter** (`?flow_status=`): One of `pending`, `approved`, `denied`. Silently ignored if the form has no approval flow.

**Workflow state filter** (`?state=`): Filter by workflow state key (e.g. `draft`, `in_review`, `done`). Returns `400 invalid_workflow_state` if the form has no workflow.

**Sorting** (`?order=`): One of `recent` (default, newest first) or `oldest`.

**Filter composition** — all filters compose with AND across groups and OR within each group:

```
Results = (submission_sources OR)
  AND (submitter_user_ids OR)
  AND flow_status
  AND state
  AND search
  AND date_range
```

**Search behavior** — the `search` parameter searches across response content, member name/email, and guest name/email. Anonymous member identities are never searchable (privacy protection).

```bash
FORM_UUID="96bd8829-1d2a-40fe-8acf-7edb08f742dd"

# All responses
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/$FORM_UUID/responses/?all=true"

# Only automation submissions
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/$FORM_UUID/responses/?all=true&submission_sources=automation"

# Pending approval + member source + search
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/$FORM_UUID/responses/?all=true&submission_sources=member&flow_status=pending&search=bug"

# Oldest first with date range
curl -H "X-API-KEY: $DAILYBOT_API_KEY" \
  "https://api.dailybot.com/v1/forms/$FORM_UUID/responses/?all=true&order=oldest&start_date=2026-07-01&end_date=2026-07-10"
```

### Submitting a form response

`POST /v1/forms/{uuid}/responses/` creates a new response. The `content` field maps each question UUID to its answer value (strings, booleans, numbers, or arrays of scalars for multiple-choice).

**Submission modes:**

| Mode | Flags | Channel notification | Use case |
|------|-------|---------------------|----------|
| Normal | (none) | Submitter's name + avatar | Human filling a form |
| Anonymous | `anonymous: true` | Random generated name | Honest feedback without attribution |
| Automation | `automation: true` | No submitter shown | CI/CD pipeline, integration, workflow |
| Automation + Guest | `automation: true` + `guest_user` | No submitter in channel; guest identity in dashboard | External form submissions forwarded via API |

**Guest identity** — use `guest_user` to attach an external person's identity (name and email) to automation submissions. Only accepted when `automation: true`; silently ignored otherwise. Required when the form has `email_and_name_mandatory` enabled. `guest_user.full_name` max 255 chars; `guest_user.email` valid email, max 254 chars.

**Submission source** — use `submission_source` (max 512 chars) to tag which automation or integration produced the response. Stored in response metadata and returned in list/detail views. Suggested values: `"github-actions:deploy-pipeline"`, `"zapier:feedback-sync"`, `"cli:ci-release-bot"`, `"make:onboarding-flow"`.

**Validation rules:**

- `content` is required and must contain answers matching the form's questions
- `guest_user` requires `automation: true` — ignored otherwise
- If the form has `email_and_name_mandatory=true` and `automation=true`, both `guest_user.full_name` and `guest_user.email` must be provided
- Payload size limit: 64 KB maximum
- Answer values cannot be nested objects — lists must contain only scalars

```bash
# Automation mode with guest identity and source
curl -s -X POST \
  -H "X-API-KEY: $DAILYBOT_API_KEY" \
  -H "Content-Type: application/json" \
  "https://api.dailybot.com/v1/forms/{uuid}/responses/" \
  -d '{
    "content": {"<question-uuid>": "Approved"},
    "automation": true,
    "guest_user": {"full_name": "Ops Bot", "email": "ops@company.com"},
    "submission_source": "workflow:on-call-handoff"
  }'

# Anonymous submission
curl -s -X POST \
  -H "X-API-KEY: $DAILYBOT_API_KEY" \
  -H "Content-Type: application/json" \
  "https://api.dailybot.com/v1/forms/{uuid}/responses/" \
  -d '{
    "content": {"<question-uuid>": "Honest feedback about the process"},
    "anonymous": true
  }'
```

### Web app URLs for integrators

| URL | Purpose |
|-----|---------|
| `https://app.dailybot.com/forms/{form_uuid}/responses/create/` | Public fill link (share with respondents) |
| `https://app.dailybot.com/forms/{form_uuid}/responses/{response_uuid}` | Deep link to a single response in the dashboard |

## Endpoints in this group

Create, configure, and archive forms programmatically; manage questions with conditional logic; submit and transition responses through the workflow state machine.

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/forms/` | List forms |
| POST | `/v1/forms/create/` | Create a form with inline questions |
| GET | `/v1/forms/form-owners/` | List form owners |
| GET | `/v1/forms/{uuid}/` | Retrieve a form |
| PATCH | `/v1/forms/{uuid}/config/` | Update form configuration |
| DELETE | `/v1/forms/{uuid}/archive/` | Archive (deactivate) a form |
| POST | `/v1/forms/{uuid}/questions/` | Add a question to a form |
| PATCH | `/v1/forms/{uuid}/questions/{q_uuid}/` | Update a form question |
| DELETE | `/v1/forms/{uuid}/questions/{q_uuid}/delete/` | Delete a form question |
| PUT | `/v1/forms/{uuid}/questions/reorder/` | Reorder all form questions |
| GET | `/v1/forms/{uuid}/responses/` | List form responses |
| POST | `/v1/forms/{uuid}/responses/` | Create a form response |
| GET | `/v1/forms/{uuid}/responses/{response_uuid}/` | Retrieve a form response |
| PATCH | `/v1/forms/{uuid}/responses/{response_uuid}/` | Update a form response |
| DELETE | `/v1/forms/{uuid}/responses/{response_uuid}/` | Delete a form response |
| POST | `/v1/forms/{uuid}/responses/{response_uuid}/transition/` | Transition a form response state |

### GET `/v1/forms/`

**List forms**

Returns every form in the caller's organization (archived excluded by default). Supports filtering by scope, owner, searching by name, sorting by name/date/total responses, date ranges, and optional question inclusion. Capabilities — editing, response visibility, state changes — are governed by the form's permissions; owner and org admins always have full access.

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

#### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `search` | string | No | Case-insensitive search on form name. Matches system forms and user-created forms. Max 200 chars. |
| `filter` | string | No | Scope filter. One of: all, public, approval, workflow, archived. Default: all org forms. Deprecated value: me — use owner_user_ids with your own UUID instead. |
| `owner_user_ids` | string (CSV) | No | Filter by form owner UUIDs. Comma-separated (max 50), OR semantics. ANDs with every other param (search, filter, pagination, ordering). Cross-org UUIDs never match. Replaces the deprecated filter=me. |
| `order` | string | No | Sort field. One of: alphabetical, recent, total. Default: recent. |
| `is_ascend` | boolean | No | Sort direction. true for ascending, false for descending. Default: false. |
| `include` | string | No | Comma-separated list of extra fields to include. Currently supports: questions (returns each form's questions with UUID, label, type, options). |
| `include_archived` | boolean | No | When true, includes archived forms in results. Not needed when using filter=archived. Default: false. |
| `start_date` | string (YYYY-MM-DD) | No | Filter forms created on or after this date. Inclusive, caller's timezone. |
| `end_date` | string (YYYY-MM-DD) | No | Filter forms created on or before this date. Inclusive, caller's timezone. |
| `offset` | integer | No | Pagination offset. Default: 0. |
| `limit` | integer | No | Page size. Default: 25, max: 50. |

#### Response body

```json
{
  "count": "integer",
  "next": "string | null",
  "previous": "string | null",
  "results": "array<{ uuid, name, is_active, collect_responses_anonymously, privacy, shortcut, start_on, end_on, is_archived, workflow_enabled, approval_flow_enabled, created_at, questions? }>"
}
```

#### Error codes

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

#### Example (curl)

```bash
curl -sS 'https://api.dailybot.com/v1/forms/?filter=workflow&order=alphabetical&is_ascend=true' \
  -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

#### Notes

- When include=questions is set, each form object includes a questions array with UUID, label, type, required flag, and options for each question.
- Deprecated: filter=me — use owner_user_ids with your own user UUID instead. Legacy clients keep working: me still resolves to the caller's owner scope and intersects with any explicit owner_user_ids. The me scoping on form responses endpoints is unrelated and NOT deprecated. Both filter=me and available_on_list_view remain accepted indefinitely; removal will be announced as a separate changelog entry with its own migration window.
- Deprecated: available_on_list_view — still accepted on POST /v1/forms/create/ and PATCH /v1/forms/{uuid}/config/ but ignored server-side. List visibility is now org-wide. To hide a form from the list, archive it instead.

### POST `/v1/forms/create/`

**Create a form with inline questions**

Creates a new form with at least one question and optional configuration (workflow, permissions, approval, ChatOps command, report channels). Requires admin or manager role.

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

#### Request body

```json
{
  "name": "string (required, min 3)",
  "questions": "array (required, min 1)",
  "report_channels": "string[] (max 3)",
  "generate_short_question": "boolean (optional, top-level)"
}
```

#### Response body

```json
{
  "uuid": "string (uuid)",
  "name": "string",
  "questions": "array",
  "report_channels": "array",
  "public_url": "string|null"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | questions_required, unknown_field, report_channel_not_found, too_many_report_channels |

#### Example (curl)

```bash
curl -sS -X POST 'https://api.dailybot.com/v1/forms/create/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json' -d '{"name":"Incident Report","questions":[{"type":"text","label":"What happened?","short_question":"Description"}]}'
```

#### Notes

- Field aliases: question_type for type, question for label. short_question required on each question unless generate_short_question: true at request level.

### GET `/v1/forms/form-owners/`

**List form owners**

Paginated, searchable picker of org members who own at least one non-archived form. Only active, approved members appear. Ordered by full_name ascending. Designed for UI pickers: a 1000-member org returns only its (typically few) form owners, not the whole member directory.

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

#### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `search` | string | No | Case-insensitive search on member name and email. Email is matched server-side for all callers but the email value is only returned to callers with email visibility (admins, managers, team admins). |
| `offset` | integer | No | Pagination offset. Default: 0. |
| `limit` | integer | No | Page size. Default: 20, max: 50. |

#### Response body

```json
{
  "count": "integer",
  "next": "string | null",
  "previous": "string | null",
  "results": "array<{ uuid, full_name, image, role, email (conditional — present only for admin/manager/team-admin-scoped callers) }>"
}
```

#### Error codes

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

#### Example (curl)

```bash
curl -sS 'https://api.dailybot.com/v1/forms/form-owners/?search=serg&limit=20' \
  -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

#### Notes

- Member emails are hidden in picker payloads. The email field appears ONLY when the caller has email visibility — org admins, managers, and team admins. Member-scoped callers receive rows without the email key (omitted entirely, never null). API keys inherit the key owner's role. search still matches on email server-side for every caller, but the value is never echoed back to callers without visibility.
- The role field contains the org role slug: ADMIN_ORG, MANAGER, ADMIN, MEMBER, or GUEST.

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

**Retrieve a form**

Retrieve a form by UUID. The read gate is org membership — any authenticated member of the organization can read any form. The privacy and available_on_list_view fields do not affect who can read the form; capabilities like editing, seeing responses, and changing workflow states are governed by the form's per-scope permissions (owner and org admins always have full access).

- **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 | — |

#### Response body

```json
{
  "uuid": "string (uuid)",
  "name": "string",
  "is_active": "boolean",
  "collect_responses_anonymously": "boolean",
  "privacy": "string",
  "questions": "array",
  "workflow": "object",
  "created_at": "string (ISO 8601)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `429` | Throttled — Retry-After header set |
| `404` | Form not found or caller is not an org member |

#### Example (curl)

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

#### Notes

- The detail read gate is org membership. The privacy field reflects the form's submission scope (OWNER, TEAM, EVERYONE), not who can read the form definition. The available_on_list_view field is deprecated and has no effect — all org forms now appear in the list endpoint.

### PATCH `/v1/forms/{uuid}/config/`

**Update form configuration**

Partial update of form metadata and configuration. Unknown fields return 400 unknown_field. approvers and permission audiences use full-replace semantics.

- **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
{
  "name": "string?",
  "workflow": "object?",
  "who_can_edit": "object?",
  "report_channels": "string[]?"
}
```

#### Response body

```json
{
  "id": "uuid",
  "name": "string",
  "questions": "array",
  "workflow": "object"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | unknown_field, workflow_requires_states, invalid_permission_audience, command_already_exists |
| `404` | form_not_found |

#### Example (curl)

```bash
curl -sS -X PATCH 'https://api.dailybot.com/v1/forms/{uuid}/config/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json' -d '{"allow_public_responses":true}'
```

#### Notes

- report_channels array fully replaces the current set (max 3). Channel IDs must exist in GET /v1/report-channels/.

### DELETE `/v1/forms/{uuid}/archive/`

**Archive (deactivate) a form**

Sets the form inactive and archived. Idempotent — re-archiving returns 204.

- **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 | — |

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `404` | form_not_found |

#### Example (curl)

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

### POST `/v1/forms/{uuid}/questions/`

**Add a question to a form**

Add a question to a form. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.

- **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
{
  "type": "string",
  "label": "string",
  "short_question": "string (required unless generate_short_question)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | short_question_required, invalid_question_type, question_uuids_incomplete |

#### Example (curl)

```bash
curl -sS -X POST 'https://api.dailybot.com/v1/forms/{uuid}/questions/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json'
```

### PATCH `/v1/forms/{uuid}/questions/{q_uuid}/`

**Update a form question**

Update a form question. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.

- **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 | — |
| `q_uuid` | string (uuid) | Yes | — |

#### Request body

```json
{
  "type": "string",
  "label": "string",
  "short_question": "string (required unless generate_short_question)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | short_question_required, invalid_question_type, question_uuids_incomplete |

#### Example (curl)

```bash
curl -sS -X PATCH 'https://api.dailybot.com/v1/forms/{uuid}/questions/{q_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json'
```

### DELETE `/v1/forms/{uuid}/questions/{q_uuid}/delete/`

**Delete a form question**

Delete a form question. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.

- **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 | — |
| `q_uuid` | string (uuid) | Yes | — |

#### Request body

```json
{
  "type": "string",
  "label": "string",
  "short_question": "string (required unless generate_short_question)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | short_question_required, invalid_question_type, question_uuids_incomplete |

#### Example (curl)

```bash
curl -sS -X DELETE 'https://api.dailybot.com/v1/forms/{uuid}/questions/{q_uuid}/delete/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json'
```

### PUT `/v1/forms/{uuid}/questions/reorder/`

**Reorder all form questions**

Reorder all form questions. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.

- **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
{
  "question_uuids": "uuid[] (required, complete set)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `401` | Missing or invalid credential |
| `403` | Insufficient permissions (admin/manager required for write) |
| `429` | Rate limited — Retry-After header set |
| `400` | short_question_required, invalid_question_type, question_uuids_incomplete |

#### Example (curl)

```bash
curl -sS -X PUT 'https://api.dailybot.com/v1/forms/{uuid}/questions/reorder/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json'
```

#### Notes

- question_uuids must include every question UUID exactly once.

### GET `/v1/forms/{uuid}/responses/`

**List form responses**

Paginated list of form responses. By default returns only the caller's own responses. With all=true or any advanced filter (submission_sources, submitter_user_ids, flow_status), returns all responses and requires VIEW_REPORTS permission. Supports full-text search, submission source filtering, workflow state filtering, approval flow status, date ranges, and sorting.

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

#### Path parameters

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

#### Query parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `all` | boolean | No | Return all responses. Requires VIEW_REPORTS permission on the form. Default: false (own responses only). |
| `user` | string (uuid) | No | Filter by specific submitter UUID. Requires VIEW_REPORTS permission. Invalid UUIDs return 400 invalid_user_identifier. |
| `search` | string | No | Full-text search across response content, submitter name, and submitter email. Anonymous member identities are not searchable (privacy). Max 256 chars. |
| `submission_sources` | string (CSV) | No | Filter by submission origin. Comma-separated, OR semantics. Values: member, anonymous, automation, public. Requires VIEW_REPORTS permission. |
| `submitter_user_ids` | string (CSV) | No | Filter by submitter UUIDs. Comma-separated (max 50), OR semantics. Requires VIEW_REPORTS permission. |
| `flow_status` | string | No | Approval flow status. One of: pending, approved, denied. Silently ignored if the form has no approval flow. Requires VIEW_REPORTS permission. |
| `state` | string | No | Workflow state key (e.g. draft, in_review, done). Returns 400 invalid_workflow_state if the form has no workflow. |
| `order` | string | No | Sort direction. One of: recent (newest first), oldest. Default: recent. |
| `is_ascend` | boolean | No | When true, equivalent to order=oldest. Default: false. |
| `start_date` | string (YYYY-MM-DD) | No | Filter by creation date range start. Inclusive, caller's timezone. |
| `end_date` | string (YYYY-MM-DD) | No | Filter by creation date range end. Inclusive, caller's timezone. |
| `offset` | integer | No | Pagination offset. Default: 0. |
| `limit` | integer | No | Page size. Default: 25, max: 50. |

#### Response body

```json
{
  "count": "integer",
  "next": "string | null",
  "previous": "string | null",
  "results": "array<{ uuid, user, is_dailybot_bot, is_guest_user, is_anonymous, guest_user, submission_source, flow_status, current_state, content, response_completed, has_issue, created_at, updated_at }>"
}
```

#### Error codes

| Status | When |
|--------|------|
| `400` | Validation error (invalid_submission_sources, invalid_submitter_user_id, too_many_submitter_user_ids, invalid_flow_status, invalid_workflow_state, invalid_user_identifier, search_query_too_long, invalid_date_range) |
| `401` | Missing/invalid/expired credential |
| `403` | Caller lacks VIEW_REPORTS permission for advanced filters (form_response_view_all_forbidden) |
| `429` | Throttled — Retry-After header set |

#### Example (curl)

```bash
curl -sS 'https://api.dailybot.com/v1/forms/{uuid}/responses/?all=true&submission_sources=automation,public&order=recent' \
  -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

#### Notes

- All filters compose with AND across groups and OR within each group. Example: submission_sources=member,automation AND flow_status=pending returns member OR automation responses that are pending approval.
- Using any advanced filter (submission_sources, submitter_user_ids, flow_status) automatically implies all=true and requires VIEW_REPORTS permission.

### POST `/v1/forms/{uuid}/responses/`

**Create a form response**

Submit a new response to a form. The content field maps each question UUID to its answer value. Optionally use automation mode (no submitter attribution), anonymous mode (random generated name), guest identity (external person metadata), or a submission source label for traceability.

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

#### Path parameters

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

#### Request body

```json
{
  "content": "object (required) — answers keyed by question UUID. Values can be strings, booleans, numbers, or arrays of scalars for multiple-choice.",
  "automation": "boolean (optional, default: false) — submit as automation; channel notifications show no submitter. Response marked with is_dailybot_bot=true.",
  "anonymous": "boolean (optional, default: false) — submit anonymously; channel notifications show a random generated name.",
  "guest_user": "object (optional) — guest identity for the submission: { full_name: string (max 255), email: string (max 254) }. Only accepted when automation=true; silently ignored otherwise. Required when form has email_and_name_mandatory enabled.",
  "submission_source": "string (optional, max 512) — free-text provenance label stored in response metadata (e.g. \"github-actions:deploy-pipeline\", \"zapier:feedback-sync\")"
}
```

#### Response body

```json
{
  "uuid": "string (uuid)",
  "form": "string (uuid)",
  "content": "object — question UUID → answer value",
  "response_completed": "boolean",
  "has_issue": "boolean",
  "blockers_status": "string | null",
  "is_anonymous": "boolean",
  "is_dailybot_bot": "boolean — true when submitted as automation",
  "is_guest_user": "boolean — true when guest identity was recorded",
  "guest_user": "object | null — { full_name, email } when guest identity exists",
  "submission_source": "string | null — provenance label from metadata",
  "created_at": "string (ISO 8601)"
}
```

#### Error codes

| Status | When |
|--------|------|
| `400` | Validation error (missing content, invalid question UUIDs, required questions not answered, guest_user_required when form mandates name+email, invalid email format, submission_source exceeds 512 chars) |
| `401` | Missing/invalid/expired credential |
| `403` | Authenticated but not permitted |
| `404` | Form not found or not visible |
| `413` | Request body exceeds 64 KB limit |
| `429` | Throttled — Retry-After header set |

#### Example (curl)

```bash
curl -s -X POST \
  -H 'X-API-KEY: $DAILYBOT_API_KEY' \
  -H 'Content-Type: application/json' \
  'https://api.dailybot.com/v1/forms/{uuid}/responses/' \
  -d '{
    "content": {"<question-uuid>": "Approved"},
    "automation": true,
    "guest_user": {"full_name": "Ops Bot", "email": "ops@company.com"},
    "submission_source": "workflow:on-call-handoff"
  }'
```

#### Notes

- When automation is true, the response appears without user attribution in channel notifications — ideal for CI/CD pipelines, web form bridges, or webhook forwarding. The is_dailybot_bot field in the response confirms automation mode.
- When anonymous is true, a random generated name (e.g., "Purple Elephant") replaces the real submitter in channel notifications. If both automation and anonymous are true, automation takes precedence.
- Use guest_user to attach external identity (name + email) to automation submissions. Required when the form has email_and_name_mandatory enabled. Use submission_source to tag which integration or workflow produced the response.

### GET `/v1/forms/{uuid}/responses/{response_uuid}/`

**Retrieve a form response**

Retrieve a single form response identified by uuid. Returns current_state, allowed_transitions, and content.

- **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 | — |
| `response_uuid` | string (uuid) | Yes | — |

#### Response body

```json
{
  "uuid": "string (uuid)",
  "form": "string (uuid)",
  "content": "array",
  "current_state": "string",
  "allowed_transitions": "array<string>",
  "response_completed": "boolean",
  "has_issue": "boolean",
  "blockers_status": "string | null",
  "is_anonymous": "boolean",
  "is_dailybot_bot": "boolean",
  "is_guest_user": "boolean",
  "guest_user": "object | null — { full_name, email }",
  "submission_source": "string | null",
  "flow_status": "string | null — approval status: approved, denied, or null (pending/no flow)",
  "created_at": "string (ISO 8601)",
  "updated_at": "string (ISO 8601)"
}
```

#### 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/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### PATCH `/v1/forms/{uuid}/responses/{response_uuid}/`

**Update a form response**

Update a form response identified by uuid. Response returns the updated resource including current_state and allowed_transitions.

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

#### Path parameters

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

#### Request body

```json
{
  "content": "array (optional)",
  "response_completed": "boolean (optional)"
}
```

#### Response body

```json
{
  "uuid": "string (uuid)",
  "form": "string (uuid)",
  "content": "array",
  "current_state": "string",
  "allowed_transitions": "array<string>",
  "response_completed": "boolean",
  "updated_at": "string (ISO 8601)"
}
```

#### 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/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### DELETE `/v1/forms/{uuid}/responses/{response_uuid}/`

**Delete a form response**

Delete a form response

- **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 | — |
| `response_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/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

### POST `/v1/forms/{uuid}/responses/{response_uuid}/transition/`

**Transition a form response state**

Runs the state machine transition. Body: to_state, optional note.

- **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 | — |
| `response_uuid` | string (uuid) | Yes | — |

#### Request body

```json
{
  "to_state": "string (required)",
  "note": "string (optional)"
}
```

#### Response body

```json
{
  "uuid": "string (uuid)",
  "form": "string (uuid)",
  "current_state": "string",
  "allowed_transitions": "array<string>",
  "content": "array",
  "updated_at": "string (ISO 8601)"
}
```

#### 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 |
| `409` | State-machine conflict |

#### Example (curl)

```bash
curl -sS -X POST 'https://api.dailybot.com/v1/forms/{uuid}/responses/{response_uuid}/transition/' -H 'X-API-KEY: $DAILYBOT_API_KEY'
```

---

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

