# Deftform

> Work with your Deftform forms from a workflow: read the forms in your workspace and the questions on them, pull submissions with their answers keyed by question, get a PDF of any one of them, record new responses from another system, and open, close or reconfigure a form as the workflow goes.

App · Forms & Surveys · 11 actions. Web page: https://docs.lodol.com/docs/integrations/deftform

## Actions

### Close a form

Stop a form accepting responses, and optionally set the message people see instead. Use it to close registration on a deadline, or once a place limit is reached.

**Inputs**

- Form to close (`form_id`, text, required): Which of your Deftform forms this step works on.
- Message while closed (`closed_message`, text): What visitors see in place of the form. Leave blank to keep the message it already has.

**Outputs**

- `form_id` (text)
- `is_closed` (true/false)
- `name` (text)
- `settings_changed` (list)
- `updated_at` (text)

**Example output**

```json
{
  "form_id": "OUm6T9",
  "is_closed": true,
  "name": "Contact us",
  "settings_changed": [
    "is_closed"
  ],
  "updated_at": "2026-09-17T09:14:22.000000Z"
}
```

### Get a form

Read one form and all of its fields, including the ID of each field. Use it before a 'Submit a response' step, or to check what a form is asking for.

**Inputs**

- Form to read (`form_id`, text, required): Which of your Deftform forms this step works on.

**Outputs**

- `after_message` (text)
- `after_redirect_delay` (number)
- `after_redirect_url` (text)
- `captcha` (text)
- `capture_location` (true/false)
- `closed_at` (text)
- `closed_message` (text)
- `created_at` (text)
- `cta_label` (text)
- `description` (text)
- `discord_enabled` (true/false)
- `field_count` (number)
- `fields` (list)
- `google_sheets_enabled` (true/false)
- `hubspot_enabled` (true/false)
- `id` (text)
- `is_closed` (true/false)
- `name` (text)
- `seo_allow_bots` (true/false)
- `seo_description` (text)
- `seo_title` (text)
- `show_formtitle` (true/false)
- `slack_enabled` (true/false)
- `slug` (text)
- `updated_at` (text)

**Example output**

```json
{
  "after_message": "<p>Thank you, we'll be in touch.</p>",
  "after_redirect_delay": null,
  "after_redirect_url": null,
  "captcha": null,
  "capture_location": false,
  "closed_at": null,
  "closed_message": null,
  "created_at": "2026-09-17T21:24:25.000000Z",
  "cta_label": null,
  "description": null,
  "discord_enabled": false,
  "field_count": 2,
  "fields": [
    {
      "custom_key": "email_address",
      "label": "Email address",
      "options": null,
      "placeholder": "you@example.com",
      "required": true,
      "type": "email",
      "uuid": "f5fb1e1a-0a70-486b-90d9-67146b125a33"
    }
  ],
  "google_sheets_enabled": false,
  "hubspot_enabled": false,
  "id": "OUm6T9",
  "is_closed": false,
  "name": "Contact us",
  "seo_allow_bots": false,
  "seo_description": null,
  "seo_title": null,
  "show_formtitle": true,
  "slack_enabled": false,
  "slug": "contact-us-OUm6T9",
  "updated_at": "2026-09-17T21:24:25.000000Z"
}
```

### Get a response

Read one submission and its answers. If it's been deleted the step says so and carries on, rather than failing the workflow.

**Inputs**

- Form (`form_id`, text, required): Which of your Deftform forms this step works on.
- Response (`response_id`, text, required): The submission's ID: the 'id' from a 'List responses' step, or the one a webhook sent you.

**Outputs**

- `found` (true/false)
- `response` (object)

**Example output**

```json
{
  "found": true,
  "response": {
    "answers": {
      "Email address": "ada@example.com",
      "Name": "Ada Lovelace"
    },
    "created_at": "2026-09-17T21:26:11.000000Z",
    "fields": [
      {
        "label": "Name",
        "response": "Ada Lovelace"
      },
      {
        "label": "Email address",
        "response": "ada@example.com"
      }
    ],
    "id": "b8384cd3-532b-416e-b450-94a7d715e3bb",
    "is_incomplete": false,
    "number": 9,
    "number_formatted": "9",
    "referrer": null
  }
}
```

### Get a response as a PDF

Ask Deftform for a PDF summary of one submission and get back a link to it. The link expires a few minutes after it's made, so download or forward it in the same run.

**Inputs**

- Response (`response_id`, text, required): The submission's ID: the 'id' from a 'List responses' step, or the one a webhook sent you.

**Outputs**

- `expires_in_seconds` (number)
- `response_id` (text)
- `url` (text)

**Example output**

```json
{
  "expires_in_seconds": 300,
  "response_id": "b8384cd3-532b-416e-b450-94a7d715e3bb",
  "url": "https://returnpdf.example.r2.cloudflarestorage.com/1789680388_document.pdf?X-Amz-Expires=300&X-Amz-Signature=..."
}
```

### Get workspace details

Read the connected Deftform workspace: its name, its owner, how many members it has, its time zone and the defaults new forms inherit.

**Inputs**: None.

**Outputs**

- `after_message` (text)
- `after_redirect_url` (text)
- `created_at` (text)
- `discord_connected` (true/false)
- `field_error_message` (text)
- `locale` (text)
- `max_upload_size_mb` (number)
- `member_count` (number)
- `name` (text)
- `owner` (object)
- `reply_to_email` (text)
- `slack_connected` (true/false)
- `timezone` (text)

**Example output**

```json
{
  "after_message": "<p>Thank you, we'll be in touch.</p>",
  "after_redirect_url": null,
  "created_at": "2026-08-20T08:24:20.000000Z",
  "discord_connected": false,
  "field_error_message": "This field is mandatory.",
  "locale": "en",
  "max_upload_size_mb": 50,
  "member_count": 0,
  "name": "Acme Forms",
  "owner": {
    "email": "ada@example.com",
    "email_verified_at": "2026-03-28T20:08:58.000000Z",
    "name": "Ada Lovelace"
  },
  "reply_to_email": "hello@example.com",
  "slack_connected": false,
  "timezone": "UTC"
}
```

### List form fields

Read the questions on a form: each one's label, its type, whether it's required, and the ID a submitted answer is filed under.

**Inputs**

- Form (`form_id`, text, required): Which of your Deftform forms this step works on.

**Outputs**

- `count` (number)
- `fields` (list)
- `form_id` (text)

**Example output**

```json
{
  "count": 1,
  "fields": [
    {
      "custom_key": "email_address",
      "label": "Email address",
      "options": null,
      "placeholder": "you@example.com",
      "required": true,
      "type": "email",
      "uuid": "f5fb1e1a-0a70-486b-90d9-67146b125a33"
    }
  ],
  "form_id": "OUm6T9"
}
```

### List forms

Read every form in your Deftform workspace: its name, its ID and how many fields it has. Use it to find a form's ID, or to loop over all of them.

**Inputs**

- Name contains (`name_contains`, text): Only forms whose name contains this text. Leave blank for all of them.

**Outputs**

- `count` (number)
- `forms` (list)

**Example output**

```json
{
  "count": 1,
  "forms": [
    {
      "after_message": "<p>Thank you, we'll be in touch.</p>",
      "after_redirect_delay": null,
      "after_redirect_url": null,
      "captcha": null,
      "capture_location": false,
      "closed_at": null,
      "closed_message": null,
      "created_at": "2026-09-17T21:24:25.000000Z",
      "cta_label": null,
      "description": null,
      "discord_enabled": false,
      "field_count": 2,
      "google_sheets_enabled": false,
      "hubspot_enabled": false,
      "id": "OUm6T9",
      "is_closed": false,
      "name": "Contact us",
      "seo_allow_bots": false,
      "seo_description": null,
      "seo_title": null,
      "show_formtitle": true,
      "slack_enabled": false,
      "slug": "contact-us-OUm6T9",
      "updated_at": "2026-09-17T21:24:25.000000Z"
    }
  ]
}
```

### List responses

Read a form's submissions, newest first. Each one comes back with its answers keyed by question, so a later step can read an answer by name. Narrow it to finished or abandoned submissions.

**Inputs**

- Form (`form_id`, text, required): Which of your Deftform forms this step works on.
- Which responses (`show`, text): Abandoned submissions are only recorded when the form has 'Track incomplete submissions' switched on. One of: `all` (All responses), `complete` (Completed responses only), `incomplete` (Incomplete responses only). Default: `all`.
- How many (`limit`, number): The most responses to return, newest first. The result also says how many matched in total. From 1 to 500. Default: `50`.

**Outputs**

- `count` (number)
- `form_id` (text)
- `has_more` (true/false)
- `responses` (list)
- `total` (number)

**Example output**

```json
{
  "count": 1,
  "form_id": "OUm6T9",
  "has_more": false,
  "responses": [
    {
      "answers": {
        "Email address": "ada@example.com",
        "Name": "Ada Lovelace"
      },
      "created_at": "2026-09-17T21:26:11.000000Z",
      "fields": [
        {
          "label": "Name",
          "response": "Ada Lovelace"
        },
        {
          "label": "Email address",
          "response": "ada@example.com"
        }
      ],
      "id": "b8384cd3-532b-416e-b450-94a7d715e3bb",
      "is_incomplete": false,
      "number": 9,
      "number_formatted": "9",
      "referrer": null
    }
  ],
  "total": 1
}
```

### Reopen a form

Let a closed form accept responses again. Everything else about the form is left alone.

**Inputs**

- Form to reopen (`form_id`, text, required): Which of your Deftform forms this step works on.

**Outputs**

- `form_id` (text)
- `is_closed` (true/false)
- `name` (text)
- `settings_changed` (list)
- `updated_at` (text)

**Example output**

```json
{
  "form_id": "OUm6T9",
  "is_closed": false,
  "name": "Contact us",
  "settings_changed": [
    "is_closed"
  ],
  "updated_at": "2026-09-17T09:14:22.000000Z"
}
```

### Submit a response

Record a response against one of your forms, as though somebody had filled it in, useful for feeding a form from another system. Deftform sends no notification emails for a response added this way.

**Inputs**

- Form to submit to (`form_id`, text, required): Which of your Deftform forms this step works on.
- Answers (`answers`, object, required): One box per question on the form. Leave a question blank to submit nothing for it. A file upload takes a link to a file you've already put somewhere public; Deftform can't accept an uploaded file here.

**Outputs**

- `created_at` (text)
- `fields_submitted` (number)
- `form_id` (text)
- `response_id` (text)
- `submitted` (true/false)

**Example output**

```json
{
  "created_at": "2026-09-17T21:26:11.000000Z",
  "fields_submitted": 2,
  "form_id": "OUm6T9",
  "response_id": "b8384cd3-532b-416e-b450-94a7d715e3bb",
  "submitted": true
}
```

### Update form settings

Change a form's name, description, button label, thank-you message, redirect, response cap, CAPTCHA or search-engine listing. Anything you leave blank is left as it is.

**Inputs**

- Form to update (`form_id`, text, required): Which of your Deftform forms this step works on.
- Form name (`name`, text): Rename the form. Up to 255 characters.
- Description (`description`, text): The description shown under the form's title. Up to 1000 characters.
- Submit button label (`cta_label`, text): What the submit button says: 'Send', 'Apply', 'Book my place'. Up to 100 characters.
- Thank-you message (`after_message`, text): What people see after they submit the form.
- Redirect to (`after_redirect_url`, text): Send people to this address after they submit. Must be a full URL including https://.
- Redirect after (`after_redirect_delay`, number): Seconds to show the thank-you message before redirecting, from 0 to 60. From 0 to 60.
- Response limit (`responses_limit`, number): Close the form automatically once it has this many responses. At least 1.
- CAPTCHA (`captcha`, text): Which spam check to put in front of the form. One of: `none` (No CAPTCHA), `altcha`, `turnstile` (Cloudflare Turnstile), `recaptcha` (Google reCAPTCHA).
- Search engine title (`seo_title`, text): The title search engines and link previews show. Up to 255 characters.
- Search engine description (`seo_description`, text): The description search engines and link previews show. Up to 500 characters.
- Other settings (`other_settings`, object): Any other Deftform form setting, by its own name (for example send_pdf_to_respondent or seo_allow_bots). This is also the only way to empty a setting: give it no value here and it is cleared, whereas a blank box above leaves the setting as it is. Use the 'Close a form' step to close one.

**Outputs**

- `form_id` (text)
- `name` (text)
- `settings_changed` (list)
- `updated_at` (text)

**Example output**

```json
{
  "form_id": "OUm6T9",
  "name": "Contact us",
  "settings_changed": [
    "cta_label",
    "name"
  ],
  "updated_at": "2026-09-17T09:14:22.000000Z"
}
```
