Forms · API Reference · Developers
Create, configure, and archive forms programmatically; manage questions with conditional logic; submit and transition responses through the workflow state machine.
On this page
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.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| search | string | Optional | Case-insensitive search on form name. Matches system forms and user-created forms. Max 200 chars. |
| filter | string | Optional | 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) | Optional | 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 | Optional | Sort field. One of: alphabetical, recent, total. Default: recent. |
| is_ascend | boolean | Optional | Sort direction. true for ascending, false for descending. Default: false. |
| include | string | Optional | Comma-separated list of extra fields to include. Currently supports: questions (returns each form's questions with UUID, label, type, options). |
| include_archived | boolean | Optional | When true, includes archived forms in results. Not needed when using filter=archived. Default: false. |
| start_date | string (YYYY-MM-DD) | Optional | Filter forms created on or after this date. Inclusive, caller's timezone. |
| end_date | string (YYYY-MM-DD) | Optional | Filter forms created on or before this date. Inclusive, caller's timezone. |
| offset | integer | Optional | Pagination offset. Default: 0. |
| limit | integer | Optional | Page size. Default: 25, max: 50. |
Response
{
"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? }>"
}Errors
| 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 |
curl -sS 'https://api.dailybot.com/v1/forms/?filter=workflow&order=alphabetical&is_ascend=true' \
-H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- 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.
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.
Request body
{
"name": "string (required, min 3)",
"questions": "array (required, min 1)",
"report_channels": "string[] (max 3)",
"generate_short_question": "boolean (optional, top-level)"
}Response
{
"uuid": "string (uuid)",
"name": "string",
"questions": "array",
"report_channels": "array",
"public_url": "string|null"
}Errors
| 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 |
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"}]}'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- Field aliases: question_type for type, question for label. short_question required on each question unless generate_short_question: true at request level.
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.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| search | string | Optional | 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 | Optional | Pagination offset. Default: 0. |
| limit | integer | Optional | Page size. Default: 20, max: 50. |
Response
{
"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) }>"
}Errors
| 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 |
curl -sS 'https://api.dailybot.com/v1/forms/form-owners/?search=serg&limit=20' \
-H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- 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.
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).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Response
{
"uuid": "string (uuid)",
"name": "string",
"is_active": "boolean",
"collect_responses_anonymously": "boolean",
"privacy": "string",
"questions": "array",
"workflow": "object",
"created_at": "string (ISO 8601)"
}Errors
| 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 |
curl -sS -X GET 'https://api.dailybot.com/v1/forms/{uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- 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.
Update form configuration
Partial update of form metadata and configuration. Unknown fields return 400 unknown_field. approvers and permission audiences use full-replace semantics.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Request body
{
"name": "string?",
"workflow": "object?",
"who_can_edit": "object?",
"report_channels": "string[]?"
}Response
{
"id": "uuid",
"name": "string",
"questions": "array",
"workflow": "object"
}Errors
| 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 |
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}'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- report_channels array fully replaces the current set (max 3). Channel IDs must exist in GET /v1/report-channels/.
Archive (deactivate) a form
Sets the form inactive and archived. Idempotent — re-archiving returns 204.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Errors
| 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 |
curl -sS -X DELETE 'https://api.dailybot.com/v1/forms/{uuid}/archive/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Add a question to a form
Add a question to a form. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Request body
{
"type": "string",
"label": "string",
"short_question": "string (required unless generate_short_question)"
}Errors
| 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 |
curl -sS -X POST 'https://api.dailybot.com/v1/forms/{uuid}/questions/' -H 'X-API-KEY: $DAILYBOT_API_KEY' -H 'Content-Type: application/json'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Update a form question
Update a form question. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| q_uuid | string (uuid) | Required | — |
Request body
{
"type": "string",
"label": "string",
"short_question": "string (required unless generate_short_question)"
}Errors
| 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 |
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'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Delete a form question
Delete a form question. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| q_uuid | string (uuid) | Required | — |
Request body
{
"type": "string",
"label": "string",
"short_question": "string (required unless generate_short_question)"
}Errors
| 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 |
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'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Reorder all form questions
Reorder all form questions. Question types: text, boolean, multiple_choice, numeric. Max 50 questions per form.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Request body
{
"question_uuids": "uuid[] (required, complete set)"
}Errors
| 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 |
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'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- question_uuids must include every question UUID exactly once.
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.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| all | boolean | Optional | Return all responses. Requires VIEW_REPORTS permission on the form. Default: false (own responses only). |
| user | string (uuid) | Optional | Filter by specific submitter UUID. Requires VIEW_REPORTS permission. Invalid UUIDs return 400 invalid_user_identifier. |
| search | string | Optional | 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) | Optional | Filter by submission origin. Comma-separated, OR semantics. Values: member, anonymous, automation, public. Requires VIEW_REPORTS permission. |
| submitter_user_ids | string (CSV) | Optional | Filter by submitter UUIDs. Comma-separated (max 50), OR semantics. Requires VIEW_REPORTS permission. |
| flow_status | string | Optional | Approval flow status. One of: pending, approved, denied. Silently ignored if the form has no approval flow. Requires VIEW_REPORTS permission. |
| state | string | Optional | Workflow state key (e.g. draft, in_review, done). Returns 400 invalid_workflow_state if the form has no workflow. |
| order | string | Optional | Sort direction. One of: recent (newest first), oldest. Default: recent. |
| is_ascend | boolean | Optional | When true, equivalent to order=oldest. Default: false. |
| start_date | string (YYYY-MM-DD) | Optional | Filter by creation date range start. Inclusive, caller's timezone. |
| end_date | string (YYYY-MM-DD) | Optional | Filter by creation date range end. Inclusive, caller's timezone. |
| offset | integer | Optional | Pagination offset. Default: 0. |
| limit | integer | Optional | Page size. Default: 25, max: 50. |
Response
{
"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 }>"
}Errors
| 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 |
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'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- 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.
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.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
Request body
{
"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
{
"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)"
}Errors
| 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 |
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": "[email protected]"},
"submission_source": "workflow:on-call-handoff"
}'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
- 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.
Retrieve a form response
Retrieve a single form response identified by uuid. Returns current_state, allowed_transitions, and content.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| response_uuid | string (uuid) | Required | — |
Response
{
"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)"
}Errors
| Status | When |
|---|---|
| 401 | Missing/invalid/expired credential |
| 403 | Authenticated but not permitted |
| 429 | Throttled - Retry-After header set |
| 404 | Not found or not visible |
curl -sS -X GET 'https://api.dailybot.com/v1/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Update a form response
Update a form response identified by uuid. Response returns the updated resource including current_state and allowed_transitions.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| response_uuid | string (uuid) | Required | — |
Request body
{
"content": "array (optional)",
"response_completed": "boolean (optional)"
}Response
{
"uuid": "string (uuid)",
"form": "string (uuid)",
"content": "array",
"current_state": "string",
"allowed_transitions": "array<string>",
"response_completed": "boolean",
"updated_at": "string (ISO 8601)"
}Errors
| 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 |
curl -sS -X PATCH 'https://api.dailybot.com/v1/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Delete a form response
Delete a form response
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| response_uuid | string (uuid) | Required | — |
Errors
| Status | When |
|---|---|
| 401 | Missing/invalid/expired credential |
| 403 | Authenticated but not permitted |
| 429 | Throttled - Retry-After header set |
| 404 | Not found or not visible |
curl -sS -X DELETE 'https://api.dailybot.com/v1/forms/{uuid}/responses/{response_uuid}/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.
Transition a form response state
Runs the state machine transition. Body: to_state, optional note.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| uuid | string (uuid) | Required | — |
| response_uuid | string (uuid) | Required | — |
Request body
{
"to_state": "string (required)",
"note": "string (optional)"
}Response
{
"uuid": "string (uuid)",
"form": "string (uuid)",
"current_state": "string",
"allowed_transitions": "array<string>",
"content": "array",
"updated_at": "string (ISO 8601)"
}Errors
| 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 |
curl -sS -X POST 'https://api.dailybot.com/v1/forms/{uuid}/responses/{response_uuid}/transition/' -H 'X-API-KEY: $DAILYBOT_API_KEY'Try it
This is a copy-only helper — the request is not sent from your browser. Paste the command into your terminal to execute it.