very much work in progress enjoy what you see here very much work in progress enjoy what you see here very much work in progress enjoy what you see here very much work in progress enjoy what you see here very much work in progress enjoy what you see here

Use Gravity Forms to Power your Static Site Forms

There are so many excellent form plugins - both paid and free - that we rarely see other solutions used for WordPress sites. They are convenient, easy to use, feature-rich, and offer plenty of customizations.

We take these form plugins for granted as they almost feel like part of WordPress itself.

Forms become, once again, a challenge to solve

But what should we do when we move away from the traditional WordPress themes? For example, when we use WordPress as a headless CMS or as a data source for a Jamstack site. 🤔

Fortunately, there are plenty of alternative solutions to choose from. Sure, services like FormKeep or Netlify provide a fantastic developer experience, but we can’t go wrong with the good old Google Forms or the better-looking Typeform.

While this is all well and good, aren’t we overlooking an obvious solution?

Here’s an idea: let’s continue using our favorite WordPress form plugin to handle form submissions.

Gravity Forms REST API to rescue

Not all WordPress form plugins have a REST API, but some do. And one of these plugins is Gravity Forms. While this is not a new feature, it often remains undiscovered, perhaps because there is no mention of the REST API on its features page.

Let’s put together a working example

The REST API is disabled by default. Mark the „Enable access to the API option” as checked in the WP Admin -> Forms -> Settings -> REST API page and save the change in order to enable it.

Enabling the Gravity Forms REST API

There is no need to create an API key, as the form submission endpoint is available without authentication.

A simple example form

After creating a form with a few fields, we can now test the REST API endpoint.

Form fields

  1. Full Name - required text input
  2. Email address - required email input
  3. Phone number - phone input
  4. Message - required textarea input, minimum 10 characters

The example Gravity Forms form

Understanding the submission endpoint

The submission endpoint is accessible under the http://gravityforms.localhost/wp-json/gf/v2/forms/2/submissions URL, and the 2 represents the ID of the form.

Error response

If we send a request to the endpoint without any data to simulate a form submission with empty fields, we get a response with the following validation message:

$ curl -X POST http://gravityforms.localhost/wp-json/gf/v2/forms/2/submissions

The keys in the validation_messages object correspond to the IDs of the fields.

   "validation_messages" : {
      "1" : "This field is required.",
      "2" : "This field is required.",
      "4" : "This field is required."
   "is_valid" : false,
   "page_number" : 1,
   "source_page_number" : 1

The whole range of validation rules still apply. For example, if we send jibberish as the email address, we will receive the corresponding validation message:

    "is_valid": false,
    "validation_messages": {
        "2": "Please enter a valid email address."
    "page_number": 1,
    "source_page_number": 1

Confirmation response

While we only get back the ID of the inputs in the validation_messages object, when submitting we have to prefix it with input_.

$ curl -X POST -H "Content-Type: application/json" -d '{"input_1":"John Doe","input_2":"","input_4":"Wondering if ..."}' http://gravityforms.localhost/wp-json/gf/v2/forms/2/submissions

Once we have fulfilled the requirements, we will get a response with the confirmation details:

    "is_valid": true,
    "page_number": 0,
    "source_page_number": 1,
    "confirmation_message": "<div id='gform_confirmation_wrapper_2' class='gform_confirmation_wrapper '><div id='gform_confirmation_message_2' class='gform_confirmation_message_2 gform_confirmation_message'>Thanks for contacting us! We will get in touch with you shortly.<\\/div><\\/div>",
    "confirmation_type": "message"

A word about status codes

To determine if the submission was successful, we can use the value of the is_valid key, but we can also infer it from the status code of the response.

The status code is 400 Bad Request when there are validation errors; for successful submissions we get a 200 OK.

Submitting the form with JavaScript

It’s better if we use the input_ID format for name attribute, since we can quickly obtain the key/value pairs of the inputs using FormData.

It doesn’t matter how we structure our HTML as long as we add the match name attribute to the proper Gravity Form fields.

<form action="http://gravityforms.localhost/wp-json/gf/v2/forms/2/submissions"

        <label for="message">Message<sup>*</sup></label>
        <textarea id="message" name="input_4" required rows="5"></textarea>

        <label for="full-name">Full name<sup>*</sup></label>
        <input id="full-name" name="input_1" required type="text">

        <label for="email-address">Email address<sup>*</sup></label>
        <input id="email-address" name="input_2" required type="email">

        <label for="phone-number">Phone number</label>
        <input id="phone-number" name="input_3" type="tel">

        <button type="submit">Submit</button>


The bare minimum of JavaScript would look something like this:

const theForm = document.querySelector('form');

theForm.addEventListener('submit', event => {

    const form =;

    const body = new FormData(form),
        {action, method} = form;

    fetch(action, {
    }).then(response => response.json()).then(result => {
        if (!result.is_valid) {
            alert(`Oh no! Something went wrong, but we won't tell you what 😈`);
        } else {
            alert(`All good! 💪`);

📹 Check out the video demonstration

While this is all very rudimentary, it’s still a working example that we can improve on.

In the next article, we are going to display the validation messages for the individual inputs as well as add some other niceties.


If WordPress is used as a headless CMS, the installation remains accessible but hidden from the general public. With the proper security settings in place, using Gravity Forms’ REST API for handling the forms is a cost-effective option that provides better integration with the other moving parts.

In addition, you can still take advantage of the premium and community add-ons to integrate with other services and perform other tasks, such as generating reports, PDFs, etc.

As for the developer experience, it’s no different than using any other service that offers an endpoint.

For those who are not using WordPress as a CMS, especially agencies who are into Jamstack, having a WordPress installation with Gravity Forms serving as a form service is something worth considering.

The company of one
of Mészáros Róbert