Form Configuration Options

Last edit: Oct 10, 2023

This is an overview of all form configuration options.


To understand this topic, you should be familiar with:

Full Form example and source code

The code below presents all possible form configuration options together with the optional form implementation part that comes just after the YAML section. All possible configuration options will be explained in detail in the following section. You can play with the form generated by the example here.
You can also explore the source code on GitHub.

name: full_form_example
resource: example_record
resource_owner: anyone
redirect_to: /full-form-example
flash_alert: This is flash alert (fail)
flash_notice: This is flash notice (success)
request_allowed: false
spam_protection: "" # e.g. { recaptcha_v2: {} } - needs to be configured
          message: Email cannot be empty
        email: true
        virtual: true
- welcome_user
- ping_example_com_on_user_sign_up
  - welcome_user
callback_actions: >
  {% log "Hello from callback actions" %}
  delay: 1
  priority: low
  max_attempts: 2
  content: |-
    {% log "Hello from async callback actions - I am delayed 1 minute!" %}
  - valid_example_policy
default_payload: |-
    "properties_attributes": {
      "greeting": "Hello from default payload!"
<p>{{ form.fields.properties.greeting.value }}</p>

{% form html-class: 'my-form' %}
    <label for="form_email">Email</label>

      name="{{ form.fields.properties.email.name }}"
      value="{{ form.fields.properties.email.value }}"

     <p class="field-error"> {{ form.errors['properties.email'] }}</p>

{% endform %}

The configuration part of the form defines the API endpoint where the server listens to specific requests and invokes all actions defined in the form. The implementation part is what is displayed as HTML to your user. It is optional because sometimes you will only want to configure the server and the request will come from another source like in the example form tutorial: Building a Contact Form with Records. For more information about the implementation part head to the Rendering Form tutorial.

Required form configuration options


Either the name of your Table or User.


Optional form configuration options


To reference your form in other places you need an identifier - we use physical_file_path as identifier by default, and name as an override.

For app/forms/full_form_example.liquid - the bolded part is the default name (physical_file_path).

If you set it to something else, this will be your new form name. We recommend leaving the default, that way you can always tell your form's name from the file location.

Keep in mind that if you are referencing a form that is inside a module, all of the module naming rules apply.


Asynchronous action that will be run in the background job. This will not slow down response to the user and can be much longer.

Accepts the following parameters:

  • content: String, Liquid Template code executed asynchronously. There is no timeout set for processing this code so it is the right place for more time-consuming calculations.
  • delay: Integer, number of minutes added to the moment of form submission before the code defined in content is executed.
  • priority: String, high, default or low, defines priority of execution when executed at the same time with other callbacks.
  • max_attempts: Integer, number of executions of callback in case of an error, default is 1.

Priority timeouts

Priority Timeout
high 1 minute
default 5 minutes
low 4 hours

Keep them in mind when writing code so that it runs fast enough for its priority.


  delay: 1
  priority: low
  max_attempts: 2
  content: >
    {% log "Hello from background" %}

The example above prints the "Hello from background" string to the output of pos-cli logs staging.


Array, list of names of Authorization Policies that are protecting the form from unauthorized submission.


Boolean, controls whether a form will be available as an endpoint (which is deprecated). If false, the form will be usable only through GraphQL mutation. Default is true.


String, Liquid Template code that is executed (synchronously, which means it will slow down response to the user) as soon as the form is successfully validated.


Object, fields that are allowed to be passed to the form object together with the validation rules for each of the defined fields. Every property added to the configuration is accessible in form variable and has the following configuration options:


  • virtual: Virtual fields come in handy when there’s no direct mapping to a record attribute or when you plan on displaying a value without processing.


          virtual: true


JSON formatted String that is merged with user data provided in the form submission.
Head to the Default Payload Tutorial to learn more about it.


Array of Email Notifications names that will be executed after the form is successfully submitted.

  - welcome_user

Read more: Creating an Email Notification


Array of short text message notification names that will be executed after the form is successfully submitted.

  - welcome_user

Read more: Creating an SMS Notification


Array of API Call Notification names that will be executed after the form is successfully submitted.

  - ping_example_com_on_user_sign_up

Read more: Creating an API Call Notification


String, message that is passed to the context.flash.alert object when the form validation is raised. This type of message is usually used to warn user about some errors and is used by the system only if form submission failed.
Learn more in a separate tutorial about Flash Messages.


String, message that is passed to the context.flash.notice object when the form is valid. This type of message is usually used to notify the user about success of an operation and is used by the system only if the form submission succeeded.
Learn more about this in a separate tutorial about Flash Messages.


String, defines path of the page rendered after a successful form submission. Example: /welcome. You can use Liquid to determine what the value should be.
This property also can be set up during form submission by setting the value of the redirect_to parameter.
For example, you can have two submit buttons in your form, with different redirect_to values to send the user into different places depending on which one has been clicked.

For example, onboarding step 3 could have this code if we wanted to save the progress (by submitting form) the user made on the form and go back/forward afterwards:

<button name="redirect_to" value="/onboarding/step2">Back</button>
<button name="redirect_to" value="/onboarding/step4">Next</button>


String, defines form configuration user permissions schema.

Available values are:

  • anyone - anyone can modify the object
  • creator - only the user that previously created the object can update/delete the object with that form configuration
  • self - like owner for User resource

The table below shows all possible resource owners for different resources:

Resource Available resource owners
User self, anyone
Record creator, anyone

This is very useful when you want to restrict user permissions to modify only records that were previously created by that user.


Object, strategy and configuration for strategy. There are available strategies recaptcha_v2 and recaptcha_v3

Config for recaptcha_v2:


Config for recaptcha_v3:

    action: signup         # required, action for recaptcha V3
    minimum_score: 0.5       # optional, minimum score that we accept for recaptcha V3, default: 0.5

A separate topic explains how to add reCaptcha Spam Protection.


We are always happy to help with any questions you may have.

contact us