A newer version of

Freeform

is available.

Try Freeform 5 now →

Freeform Freeform for Craft

Headless

GraphQL Improved 4.1.0+

Freeform supports querying form layouts and form submission mutations via GraphQL. This guide assumes you have some GraphQL experience. To learn more about GraphQL and Craft, please check out the Fetch content with GraphQL guide and Craft's GraphQL API.

GraphQL

Demos

Have a look at our headless demos to get a feel for what's possible with GraphQL:

Queries

Querying Freeform data

Freeform has a root freeform query, which contains all the possible queries nested inside it to avoid conflicts with other plugins.

Querying multiple Forms

To query all or some forms, you have to use the forms query:



 



















query {
  freeform {
    forms {
      name
      handle
      pages {
        label
        rows {
          fields {
            id
            type
            label
            handle
            required
            rules
          }
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Example response data:

{
  "data": {
    "freeform": {
      "forms": [
        {
          "name": "My Form",
          "handle": "myForm",
          "pages": [
            {
              "label": "First Page",
              "rows": [
                {
                  "fields": [
                    {
                      "type": "text",
                      "label": "First Name",
                      "handle": "firstName",
                      "required": false
                    },
                    {
                      "type": "text",
                      "label": "Last Name",
                      "handle": "lastName",
                      "required": true
                    }
                  ]
                },
                {
                  "fields": [
                    {
                      "type": "submit",
                      "label": "Submit",
                      "handle": null,
                      "required": false,
                      "rules": "{\"show\":false,\"type\":\"any\",\"criteria\":[{\"tgt\":\"lastName\",\"o\":\"=\",\"val\":\"\"}]}"
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

Querying a single Form

You can query a single form directly by using the form query:



 









query {
  freeform {
    form (handle: "my-form") {
      name
      handle
      pages {
        # ...
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

Example response data:

{
  "data": {
    "freeform": {
      "form": {
        "name": "My Form",
        "handle": "myForm",
        "pages": [
          {
            "label": "First Page",
            "rows": [
              {
                "fields": [
                  {
                    "type": "text",
                    "label": "First name",
                    "handle": "firstName",
                    "required": false
                  }
                ]
              }
            ]
          }
        ]
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Querying a form field on a Craft Entry

You can query an Entry form field by using the form field name in the query: Assuming the form field's handle is myFormFieldHandle and the section is called Blog





 
 
 
 
 
 
 
 
 
 
 



query {
  entries {
    id
    title
    ...on blog_blog_Entry {
      myFormFieldHandle {
        id
        name
        fields {
          handle
          label
          type
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Example response data:

{
  "data": {
    "entries": [
      {
        "id": "226",
        "title": "Some Entry title",
        "myFormFieldHandle": {
          "id": 1,
          "name": "Simple Form",
          "fields": [
            {
              "handle": "firstName",
              "label": "First Name",
              "type": "text"
            },
            {
              "handle": null,
              "label": "Submit",
              "type": "submit"
            }
          ]
        }
      },
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Form Query Arguments

The following arguments are available when querying single or multiple forms:

Argument Type Description
id [Int] Narrow the queried forms by one or more form ID's
uid [String] Narrow the queried forms by one or more form UID's
handle [String] Narrow the queried forms by one or more form handles
limit Int Limit the amount of returned form results
offset Int Offset the returned form results
orderBy String Order the forms by a specific property
sort String Sort by asc or desc order
query {
  freeform {
    # This is just an example
    # For `id`, `uid` and `handle` - you can either pass a single value 
    # or an array of values for each argument
    form (id: 1, handle: "test", limit: 1, offset: 2, orderBy: "name", sort: "desc") {
      id
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Field Query Arguments

You can query fields by the following arguments:

Argument Type Description
id [Int] Narrow the queried fields by one or more field's ID's
hash [String] Narrow the queried fields by one or more field's UID's
handle [String] Narrow the queried fields by one or more field's handles
query {
  freeform {
    forms {
      # This is just an example
      # You can either pass a single value or an array of values for each argument
      fields (id: [1, 2, 3], handle: ["firstName", "lastName"], hash: "some-hash") {
        id
        handle
        hash
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Mutations 4.1.0+

GraphQL mutations provide a way to modify data. The actual mutations will vary depending on the schema and what it allows. There are common mutations per GraphQL object type and additional type-specific mutations.

Creating a new Submission

To create a new submission we use form-specific mutations in the form of save_<formHandle>_Submission.

Mutations take the data as arguments. We pass the values we want to use in the query as query variables.

In this example, we're using a form with the handle of contact which contains form fields for first name, last name and email. Our form also has Honeypot and ReCaptcha V3 enabled.

You can grab these values using form-specific GraphQL queries or by creating an custom endpoint on your site.

See How to Render a Form.

// Query
mutation SaveContactSubmission(
    $honeypot: FreeformHoneypotInputType,
    $reCaptcha: FreeformSubmissionReCaptchaInputType,
    $csrfToken: FreeformCsrfTokenInputType,
    $firstName: String,
    $lastName: String,
    $email: String,
    $mailingList_1bkqk7kOQ: Int,
    $mailingList_kj1l1a9qg: Int,
) {
    save_contact_Submission(
        honeypot: $honeypot
        reCaptcha: $reCaptcha
        csrfToken: $csrfToken
        firstName: $firstName
        lastName: $lastName
        email: $email
        mailingList_1bkqk7kOQ: $mailingList_1bkqk7kOQ
        mailingList_kj1l1a9qg: $mailingList_kj1l1a9qg
    ) {
        submissionId
        success
    }
}

// Query Variables
{
    "honeypot": {
        "name": "freeform_form_handle",
        "value": ""
    }
    "reCaptcha": {
        "name": "g-recaptcha-response",
        "value": "INSERT RECAPCTHA RESPONSE",
    },
    "csrfToken": {
        "name": "INSERT CSRF TOKEN NAME",
        "value": "INSERT CSRF TOKEN VALUE",
    },
    "firstName": "Solspace",
    "lastName": "Freeform",
    "email": "support@solspace.com",
    "mailingList_1bkqk7kOQ": 0,
    "mailingList_kj1l1a9qg": 1
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

Example response data:

{
    "data": {
        "save_contact_Submission": {
            "submissionId": 1982,
            "success": true,
        }
    }
}
1
2
3
4
5
6
7
8

Submission Mutation Arguments

Argument Type Description
... Arguments depending on the field layout for the form

Interfaces

Form Interface Revised 4.1.0+

These are the fields available for the FreeformFormInterface:

WARNING

FormInterface is deprecated. Please use FreeformFormInterface instead. ajax is deprecated. Please use ajaxEnabled instead.

Field Type Description
id Int ID
uid String UID
name String Name
handle String Handle
hash String The form's hash needed to submit forms
color String Color
description String Description
returnUrl String The specified return URL
storeData Boolean Are submissions being stored for this form
submissionTitleFormat String Title format used for new submission titles
submissionMutationName String The forms GraphQL mutation name for submissions
extraPostUrl String An URL that will get a POST call with the submitted data
extraPostTriggerPhrase String A keyword or phrase Freeform should check for in the output of the POST URL to know if and when there’s an error to log, e.g. ‘error’ or ‘an error occurred’.
ipCollectingEnabled Boolean Are the IP addresses being stored
ajaxEnabled Boolean Is the ajax enabled for this form
showSpinner Boolean Should the submit button show a spinner when submitting
showLoadingText Boolean Should the submit button change the button label while submitting
loadingText String The submit button loading label text
defaultStatus Int The assigned default status ID of new submissions
formTemplate String The assigned default formatting template
gtmEnabled Boolean Is the Google Tag Manager enabled for this form?
gtmId String The Google Tag Manager ID
gtmEventName String The name of the Event that will be added to Google Tag Manager's data layer
honeypot FreeformHoneypotInterface A fresh honeypot instance
csrfToken FreeformCsrfTokenInterface A fresh csrf token
reCaptcha FreeformFormReCaptchaInterface The ReCaptcha for this form
fields [FreeformFieldInterface] A list of Form's Field
pages [FreeformPageInterface] A list of Form's Page entities
mailingListName 4.1.6+, Revised in 4.1.12+ [String] The form's mailing list field handles. Use mailingList_ + unique handle/hash for mailing list field, e.g. mailingList_1bkqk7kOQ.
successMessage 4.1.6+ String The specified success message
errorMessage 4.1.6+ String The specified error message
disableSubmit 4.1.6+ Boolean Should the form’s submit button be disabled when the form is submitted
disableReset 4.1.6+ Boolean Should the form’s submit button be disabled state be reset
enctype 4.1.6+ String The form’s enctype

Field Interface Revised 4.1.0+

WARNING

FieldInterface is deprecated. Please use FreeformFieldInterface instead.

The base FreeformFieldInterface implemented by all field types. You can see specific Field Type fields here.

Field Type Description
id Int ID
type String Type
label String Label
hash String Generated unique field hash
handle String Handle
instruction String Instructions
required Boolean Is the field required
pageIndex Int The page index this field is assigned to
inputAttributes [FreeformAttributeInterface] Field's input attributes
labelAttributes [FreeformAttributeInterface] Field's label attributes
errorAttributes [FreeformAttributeInterface] Field's error attributes
instructionAttributes [FreeformAttributeInterface] Field's instruction attributes
rules 4.1.5+ String Field's rules as a JSON string

Conditional Rules 4.1.5+

The rules JSON string contains the following properties:

  • show Show or hide this item
  • type when all or any of its criteria match.
  • criteria will contain an array with the target handle, operand and value.
    • The example below would result in hiding the email field when its value is blank/empty:
      {\"show\":false,\"type\":\"any\",\"criteria\":[{\"tgt\":\"email\",\"o\":\"=\",\"val\":\"\"}]}
      
      1

Page Interface Revised 4.1.0+

WARNING

PageInterface is deprecated. Please use FreeformPageInterface instead.

Each page contains a list of FreeformRowInterface objects:

Field Type Description
index Int Index of the page
label String Page's label
rows [FreeformRowInterface] A list of FreeformRowInterface objects

Row Interface Revised 4.1.0+

WARNING

RowInterface is deprecated. Please use FreeformRowInterface instead.

Each row contains a list of fields:

Field Type Description
id String A unique hash generated for each row
fields [FreeformFieldInterface] A list of FreeformFieldInterface objects

Submission Interface Revised 4.1.0+

These are the fields available for the FreeformSubmissionInterface:

Field Type Description
id Int The ID of the submission
finished Boolean Whether the submission is finished or not
freeformPayload String The payload of the submission
hash String The generated hash for the submission
reCaptcha FreeformSubmissionReCaptchaInterface The ReCaptcha (name and value) of the submission
csrfToken FreeformCsrfTokenInterface The CSRF token (name and value) of the submission
honeypot FreeformHoneypotInterface The Honeypot (name and value) of the submission
html String The generated HTML for the submission
multiPage Boolean Whether the submission has multiple pages or not
onSuccess String The success behaviour of the submission
returnUrl String The return URL of the submission
submissionId Int The ID of the submission
submissionLimitReached Boolean Whether the form submission rate limit has been reached or not
submissionToken String The generated token for the submission
success Boolean Whether the submission is a success or not
dateCreated DateTime The created date for the submission
dateUpdated DateTime The updated date for the submission
isSpam Boolean Whether the submission is a spam or not
spamReasons String Spam reasons for the submission
user User The author of the submission
assets [Asset] The assets of the submission

Option Interface Revised 4.1.0+

WARNING

OptionsInterface is deprecated. Please use FreeformOptionInterface instead.

Field Type Description
value String Option's value
label String Option's label
checked Boolean Is the option checked

Opinion Scale Interface Revised 4.1.0+

WARNING

ScalesInterface is deprecated. Please use FreeformOpinionScaleInterface instead.

Field Type Description
value String Value
label String Label

Attribute Interface Revised 4.1.0+

WARNING

KeyValueMapInterface is deprecated. Please use FreeformAttributeInterface instead.

Field Type Description
attribute String Name of the Attribute
value String Value of the Attribute

Honeypot Interface 4.1.0+

Use FreeformHoneypotInterface.

WARNING

hash and timestamp are deprecated. Please do not use.

Field Type Description
name String Name of Honeypot
value String Value of Honeypot

CSRF Token Interface 4.1.0+

Use FreeformCsrfTokenInterface.

Field Type Description
name String Name of the CSRF token
value String Value of the CSRF token

Form ReCaptcha Interface 4.1.0+

Use FreeformFormReCaptchaInterface.

Field Type Description
name String The forms GraphQL mutation name for submissions
handle String The forms GraphQL mutation handle for submissions
enabled Boolean Is ReCaptcha enabled for this form

Submission ReCaptcha Interface 4.1.0+

Use FreeformSubmissionReCaptchaInterface.

Field Type Description
name String Name of the ReCaptcha
value String Value of the ReCaptcha

Field Types

Text

Field Type Description
value String The default value
maxLength Int Maximum length of chars allowed for this field
placeholder String Input's placeholder attribute
fields {
  ... on FreeformField_Text {
    value
    maxLength
    placeholder
  }
}
1
2
3
4
5
6
7

Textarea

Field Type Description
value String The default value
maxLength Int Maximum length of chars allowed for this field
rows Int Number of rows shown for this textarea
placeholder String Input's placeholder attribute
fields {
  ... on FreeformField_Textarea {
    value
    maxLength
    rows
    placeholder
  }
}
1
2
3
4
5
6
7
8

Select

Field Type Description
value String The default value
options [FreeformOptionInterface] The assigned options
fields {
  ... on FreeformField_Select {
    value
    options {
      value
      label
      checked
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Checkbox

Field Type Description
value String The default value
checked Boolean Should the checkbox be checked by default
fields {
  ... on FreeformField_Checkbox {
    value
    checked
  }
}
1
2
3
4
5
6

Multi-Select

Field Type Description
values [String] The default values
options [FreeformOptionInterface] The assigned options
fields {
  ... on FreeformField_MultipleSelect {
    values
    options {
      value
      label
      checked
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Checkbox Group

Field Type Description
values [String] The default values
oneLine Boolean Should this be shown in a single line
options [FreeformOptionInterface] The assigned options
fields {
  ... on FreeformField_CheckboxGroup {
    values
    oneLine
    options {
      value
      label
      checked
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

Radio Group

Field Type Description
value String The default value
options [FreeformOptionInterface] The assigned options
fields {
  ... on FreeformField_RadioGroup {
    value
    options {
      value
      label
      checked
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Email

Field Type Description
notificationId String The ID or the filename of the email template
placeholder String Input's placeholder attribute
fields {
  ... on FreeformField_Email {
    notificationId
    placeholder
  }
}
1
2
3
4
5
6

Dynamic Recipients

Field Type Description
values [String] The default values
notificationId String The ID or the filename of the email template
showAsRadio Boolean Should the field be shown as a list of radio inputs
showAsCheckboxes Boolean Should the field be shown as a list of checkbox inputs
oneLine Boolean Should radios or checkboxes be displayed in a single line
options [FreeformOptionInterface] The assigned options
fields {
  ... on FreeformField_DynamicRecipients {
    values
    notificationId
    showAsRadio
    showAsCheckboxes
    oneLine
    options {
      valuel
      label
      checked
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Number

Field Type Description
value String The default value
minLength Int Minimum length of the number
minValue Int Minimum value of the number
maxValue Int Maximum length of the number
decimalCount Int Number of decimals
decimalSeparator String The decimal separator
thousandsSeparator String The thousands separator
allowNegative Bool Allow negative numbers
placeholder String Input's placeholder attribute
fields {
  ... on FreeformField_Number {
    value
    minLength
    minValue
    maxValue
    decimalCount
    decimalSeparator
    thousandsSeparator
    allowNegative
    placeholder
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

File

Field Type Description
fileKinds [String] Allowed file kinds
maxFileSizeKB Int Maximum allowed filesize in KB
fileCount Int Number of allowed simultaneous file uploads
fields {
  ... on FreeformField_File {
    fileKinds
    maxFileSizeKB
    fileCount
  }
}
1
2
3
4
5
6
7

Confirmation

Field Type Description
targetFieldHash String Hash of the field that has to be confirmed
fields {
  ... on FreeformField_Confirmation {
    targetFieldHash
  }
}
1
2
3
4
5

Date & Time

Field Type Description
value String The default value
dateTimeType String Type of the date field. ("date", "time", "both")
generatePlaceholder Boolean Should a placeholder be auto-generated for this field
dateOrder String Order of the date chunks.
date4DigitYear Boolean Determines if the year should be displayed with 4 digits or two
dateLeadingZero Boolean Determines if the dates should use a leading zero
dateSeparator String Date separator
clock24h Boolean Should the clock use a 24h format
clockSeparator String Clock separator
clockAMPMSeparate Boolean Should the AM/PM be separated from the time by a space
useDatepicker Boolean Should the built-in datepicker be used
minDate String Specifies the minimum allowed date that can be picked
maxDate String Specifies the maximum allowed date that can be picked
fields {
  ... on FreeformField_Datetime {
    value
    dateTimeType
    generatePlaceholder
    dateOrder
    date4DigitYear
    dateLeadingZero
    dateSeparator
    clock24h
    clockSeparator
    clockAMPMSeparate
    useDatepicker
    minDate
    maxDate
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Opinion Scale

Field Type Description
value String The default value
legends [String] A list of all the assigned Legends
scales [FreeformOpinionScaleInterface] The assigned FreeformOpinionScaleInterface
fields {
  ... on FreeformField_OpinionScale {
    value
    legends
    scales {
      value
      label
    }
  }
}
1
2
3
4
5
6
7
8
9
10

Phone

Field Type Description
value String The default value
pattern String Phone number pattern
useJsMask Boolean Should the built-in pattern matcher javascript be enabled
fields {
  ... on FreeformField_Phone {
    value
    pattern
    useJsMask
  }
}
1
2
3
4
5
6
7

Rating

Field Type Description
value String The default value
maxValue Int Phone number pattern
colorIdle String Color of the unselected, unhovered rating star
colorHover String Color of the hovered rating star
colorSelected String Color of the selected rating star
fields {
  ... on FreeformField_Rating {
    value
    maxValue
    colorIdle
    colorHover
    colorSelected
  }
}
1
2
3
4
5
6
7
8
9

Regex

Field Type Description
value String The default value
pattern String Regex pattern
message String The error message to be displayed
fields {
  ... on FreeformField_Regex {
    value
    pattern
    message
  }
}
1
2
3
4
5
6
7

Signature

Field Type Description
width Int Width in pixels
height Int Height in pixels
showClearButton Boolean Determines if the "clear" button should be displayed
borderColor String Signature field border color
backgroundColor String Signature field background color
penColor String Signature field pen color
penDotSize Float The size of the pen dot
fields {
  ... on FreeformField_Signature {
    width
    height
    showClearButton
    borderColor
    backgroundColor
    penColor
    penDotSize
  }
}
1
2
3
4
5
6
7
8
9
10
11

Table

Field Type Description
useScript Boolean Should the built-in javascript for handling table rows be used
maxRows Int Number of maximum allowed rows this table can have
addButtonLabel Boolean The label for the "add row" button
addButtonMarkup String Custom html for the "add row" button
removeButtonLabel String The label for the "delete row" button
removeButtonMarkup String Custom html for the "delete row" button
tableLayout String JSON of the table layout
fields {
  ... on FreeformField_Table {
    useScript
    maxRows
    addButtonLabel
    addButtonMarkup
    removeButtonLabel
    removeButtonMarkup
    tableLayout
  }
}
1
2
3
4
5
6
7
8
9
10
11

Email Marketing

Field Type Description
hidden Boolean Should this field be a hidden field or a checkbox
fields {
  ... on FreeformField_MailingList {
    hidden
  }
}
1
2
3
4
5

Submit

Field Type Description
labelNext String Label for the "next" button
labelPrev String Label for the "previous" button
disablePrev Boolean Is the "previous" button disabled
position String Position of the buttons
fields {
  ... on FreeformField_Submit {
    labelNext
    labelPrev
    disablePrev
    position
  }
}
1
2
3
4
5
6
7
8

How to Render a Form Revised 4.1.0+

Below are the steps for being able to render your own form in the front-end using GraphQL data and another headless solution such as (but not limited to) Vue.js, Next.js, or React JS.

Overview

To be able to make a form submittable you will need several things:

  • An action entry in the POST payload that points to freeform/submit.
  • A formHash entry which you will have to retrieve from an endpoint you create.
  • A honeypot entry if you're using the Freeform Honeypot.
  • A reCaptcha entry if you're using the Freeform Captchas.
  • A csrfToken entry if you're using Craft's CSRF tokens.
  • A freeform_payload entry if you're using Encrypted Payload as the session storage type.

To get a valid formHash, honeypot, reCaptcha, csrfToken and freeform_payload, you will have to create an endpoint on your site.

Twig

If you're using Twig, here's how to return the form properties data:

{# You can attach custom form properties #}
{# https://docs.solspace.com/craft/freeform/v4/templates/queries/form/#parameters #}
{% set formProperties = {} %}
{% set form = craft.freeform.form('your_form_handle') %}
{{ form.json(formProperties) }}
1
2
3
4
5

PHP

If you're making your own endpoint via PHP, then we've outlined some simple steps to follow in order to set up a custom Freeform Module.

TIP

Make sure to read How to Build a Module if you are new to extending Craft with custom modules.

Below is an example of what your /modules/FreeformModule.php file should look like:

<?php

namespace modules;

use Craft;
use yii\base\Module;

class FreeformModule extends Module
{
    public function init()
    {
        Craft::setAlias('@modules', __DIR__);

        if (Craft::$app->getRequest()->getIsConsoleRequest()) {
            $this->controllerNamespace = 'modules\\console\\controllers';
        } else {
            $this->controllerNamespace = 'modules\\controllers';
        }

        parent::init();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Add your module to your project's application configuration by listing it in the /config/app.php file:

<?php

use modules\FreeformModule;

return [
    'modules' => [
        'freeform-module' => FreeformModule::class,
    ],
    'bootstrap' => ['freeform-module'],
];
1
2
3
4
5
6
7
8
9
10

Create a new controller for Freeform located at /modules/controllers/FormController.php:

<?php

namespace modules\controllers;

use craft\web\Controller;
use Solspace\Freeform\Freeform;
use yii\web\Response;

class FormController extends Controller
{
    protected array|bool|int $allowAnonymous = true;

    public function actionIndex(): string
    {
        return 'Welcome to the Craft Freeform Form Controller';
    }

    public function actionProperties(int $formId): Response
    {
        $formProperties = [];

        $formModel = Freeform::getInstance()->forms->getFormById($formId);

        if ($formModel) {
            $form = $formModel->getForm()->json($formProperties);

            return $this->asJson(json_decode($form));
        }

        return $this->asJson(['message' => 'Form was not found']);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Update the /config/routes.php with your new module controller actions:

<?php

return [
    'graphql/api' => 'graphql/api',
    'freeform/form' => 'freeform-module/form/index',
    'freeform/form/properties/<formId:\d+>' => 'freeform-module/form/properties',
];
1
2
3
4
5
6
7

The JSON response looks like this:

{
    "hash": "xxxxxxxx-xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "handle": "my-form-handle",
    "ajaxEnabled": true,
    "disableSubmit": true,
    "disableReset": false,
    "showSpinner": false,
    "showLoadingText": false,
    "loadingText": "Loading...",
    "class": "",
    "method": "post",
    "enctype": "application\/x-www-form-urlencoded",
    "successMessage": "Form has been submitted successfully!",
    "errorMessage": "Sorry, there was an error submitting the form. Please try again.",
    "honeypot": {
        "name": "freeform_form_handle",
        "value": ""
    },
    // If using encrypted payloads:
    "freeform_payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "anchor": "xxxxxx-form-xxxxxxxx-xxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "csrf": {
        "name": "CRAFT_CSRF_TOKEN",
        "token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    },
    "action": "freeform\/submit"
    // If using ReCaptcha:
    "reCaptcha": {
        "enabled": true,
        "handle": "reCaptcha",
        "name": "g-recaptcha-response" // or h-captcha-response
    },
    // If using mailing lists:
    "mailingListName": ["mailingList_xxxxxx"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Finished!

Have a look at our headless demos to get a feel for what's possible with GraphQL: