<- All posts

How to Send Form Data to an API in 4 Steps

Ronan McQuillan
11 min read · Feb 19, 2024

Populating API requests is one of the most basic, universal use cases for web forms. However, building forms to do this manually can be a laborious, time-consuming process. It’s also beyond the skills of most non-developers.

But there is a better way.

Today, we’re checking how Budibase can be used to send form data to APIs. Specifically, we’re going to see how we can create and store dynamic REST requests, along with custom UIs, to populate them in a matter of minutes.

Even better, we won’t need to write a single line of custom code.

Let’s jump in.

When do we need to send form data to APIs?

APIs are some of the most fundamental building blocks of how we handle data and build web solutions. They’re a method for sending data back and forth between different applications and other nodes in a defined, controlled format.

While API requests can often be populated and triggered programmatically by system events, we’re just as likely to need human inputs.

For a very basic example, say we had a data set that’s stored in a legacy application - so the easiest way to query it is via API requests.

It would be unviable for our data entry team to manually write these requests each time they need to create a record - so we need forms to create and update our data.

In other words, we need to send form data to APIs in any situation where we want to build repeatable, user-friendly workflows for populating requests.

So..

What are we building?

We’re actually going to build two forms today using an API that stores questions for a survey.

Here’s an example of the data objects that are stored for each question:

 1{
 2
 3 "id": 1,
 4
 5 "question": "Favourite programming language?",
 6
 7 "published_at": "2015-08-05T08:40:51.620Z",
 8
 9 "choices": [
10
11  {
12
13   "choice": "Swift",
14
15   "votes": 0
16
17  },
18
19  {
20
21   "choice": "Python",
22
23   "votes": 0
24
25  },
26
27  {
28
29   "choice": "Objective-C",
30
31   "votes": 0
32
33  },
34
35  {
36
37   "choice": "Ruby",
38
39   "votes": 0
40
41  }
42
43 ]
44
45}

For the purpose of our forms, we’re only worried about a handful of these attributes. These are the id, question, and choice fields.

Everything else is beyond the scope of what we want to achieve today.

Our two forms will trigger the following:

  1. A POST request for creating new records.
  2. A PUT request to update existing records.

Let’s jump right in.

How to send form data to an API with Budibase

Budibase is the fast, easy way to build advanced forms on top of any data source.

If you haven’t already, sign up for a free account now.

Join 100,000 teams building workflow apps with Budibase

1. Creating our API requests

We’ll start by creating a new Budibase application. When we do this, we’re prompted to choose which type of data we’d like to connect to.

Data Sources

Budibase features an internal low-code database, as well as dedicated connectors for all kinds of RDBMSs, NoSQL tools, APIs, and more.

Naturally, today, we’re choosing REST API.

When we do so, we’ll be brought to this panel, where we can start creating queries.

Send Form Data to API

As we said earlier, we’re eventually going to build two forms - for updating or creating records.

So, we’ll need two corresponding requests to our API.

Let’s take each one in turn.

POST request

POST requests are used to instruct the API server to create a new record. We’ll create this first since it’s going to be slightly simpler than our other request.

We’ll start by hitting Create New Query, bringing us to this page.

Create Request

First, we’ll choose a method for our REST request and input our endpoint. We can also give our request a more descriptive name.

Request

We know that our API endpoint accepts five parameters - a question and four possible answers.

All of the other attributes in the schema we saw earlier will be generated by the target application itself - so we don’t need to worry about these.

Budibase gives us the option to create bindable values that can be used as dynamic variables throughout our REST requests. We can give these default values and then assign them with real information elsewhere in our application.

We need to create a binding for each of the parameters in our REST request body. We’ll then use form inputs to populate these later.

Bindings

With these in place, we need to create the body of our request - which we can include our bindings within.

We can do this using a form interface, but since our schema that we saw earlier contains a nested array, we’re going to use the JSON editor:

JSON editor

We’ll start by adding the basic structure of our body parameters. We know from our API docs that our request body should look like this:

 1{
 2
 3 "question": "",
 4
 5 "choices": [
 6
 7  "",
 8
 9  "",
10
11  "",
12
13  ""
14
15 ]
16
17}

So, that’s what we’ll add.

JSON blob

Then, all we need to do is populate the blank values with our bindings. We can reference these in the format {{Bindings.bindingName}}.

So, our completed JSON object will be:

 1{
 2
 3 "question": "{{Binding.question}}",
 4
 5 "choices": [
 6
 7  "{{Binding.answer1}}",
 8
 9  "{{Binding.answer2}}",
10
11  "{{Binding.answer3}}",
12
13  "{{Binding.answer4}}"
14
15 ]
16
17}

Dynamic request

When we send our request, the API responds with the complete data object that’s been saved.

Send form data to api

PUT request

For our second request, we can start by duplicating this existing one.

Duplicate

Then, we’ll update our method, endpoint, and the name of our request:

API

Now, the data schema for this request is basically the same - with the addition of an extra attribute for the question’s id.

This is used to identify the record we want to update with our API request.

So, we’ll add this to our bindings and request body.

Bindigs

Once we’ve tested that and we’re happy that it works, we can start building our forms.

2. Building our POST request form

Start by heading over to Budibase’s design tab. Here, we’re given a few options for how to create our first UI. We’re going to choose Blank Screen.

Blank screen

Then, we’re prompted to give our screen a URL path. We’ll call ours /post-form.

URL

Here’s our blank screen.

UI

The first thing we’ll add is a container, with its horizontal alignment set to the center.

Container

Inside this, we’ll nest a Form component and set its width to 600px.

Form

We’ll then set its schema to our POST request.

Send form data to API

Inside our Form, we’re going to place a container with its direction set to horizontal.

Container

Inside this, we’ll place a Headline and a Button.

Headline

We’ll define what our button does in a minute. For now, we’ve simply set its Text attribute to Save.

Remember, our schema for this request consists of a question and four possible answers. So, we’ll next add four text fields beneath our container.

API form

Since we set the schema of our form to our API earlier, these are already configured to the right fields.

We just need to tidy up their display texts using the Label and Placeholder fields for each - for human readability.

Display Text

We’ll then open the Actions drawer for our button and add an Execute Query action, setting it to our POST request.

Executre query

Here, we can use the lightning bolt icon to configure values for each of our bindings.

Bindings

We can choose any value our button is exposed to to use within handlebars or JavaScript expressions.

First, we’ll click Form.

Form

And we’ll choose the relevant form field for each bindable value.

Save

Send form data to api

That’s our form completed - but we need to test it to verify that it works.

To do this, we’ll open our app preview and add some new values.

Test

We can then check that this worked in our API server’s admin panel.

Admin panel

3. Building our PUT request form

The form we’ll use to send data to our other API request is very similar to this first one, so we’ll start by duplicating our existing screen.

Duplicate

This time, we’ll set the URL path to /put-form/:id. This will allow us to pass an attribute called id to this screen later via its URL.

URL binding

We’ll start by updating our Form’s Type to Update and its Schema to our PUT request.

Form Schema

Now, we need a way for users to choose which specific entry they want to update. We could allow them to do this manually by specifying an ID. However, this isn’t a great experience, as users will need to know which ID corresponds to each question.

It’s better if we give users a way to choose from a predefined list of options.

To do this, we’ll need a GET request that returns all of our questions.

We’ll head back to the data section and add a third request, choosing GET as our method and inputting our endpoint.

Get questions

Then, back on the design tab, we’ll add another screen, setting its URL to ‘/’.

Home Screen

On our new blank screen, we’ll add a Table Block. We’ll set the Data option for this to our new request.

Table

Our choices for each row are a series of nested objects, which aren’t going to look neat in a table. We’ll use the Columns drawer to set it so that only the ID and Question fields are displayed:

All columns

We’ll also set the width of our Questions column to 50% so that the text isn’t truncated.

Width

This is much neater.

Table

When a user clicks on any of our rows, we want to navigate to the PUT form to update the relevant data object.

To do that, we need to add an on-click action.

Actions

We’re going to add a Navigate To action and set the page path to:

1/put-form/{{ Clicked row.id }}

We’re using the {{ Clicked row.id }} binding to populate the :id variable that we added to our URL earlier.

So, when we change screens, we’ll have a way of identifying the relevant entry for our PUT request.

Navigate to

Now, head back to our PUT form.

The next thing we need to do is make it so that the existing values for each of our fields are populated when a user navigates to this screen. To achieve this, we’ll add a Data Provider beneath our form.

We’ve set the Data field to our GET request.

Data provider

We then need to add a filter expression to retrieve only the row where the id attribute matches the one we stored in our URL.

Filter

We can then use the Default Value field for each of our form fields to populate this information.

Our data schema contains several nested objects, so it’s worth taking another look at what we’re dealing with.

 1{
 2
 3 "id": 1,
 4
 5 "question": "Favourite programming language?",
 6
 7 "choices": [
 8
 9  {
10
11   "choice": "Swift",
12
13   "votes": 2048
14
15  },
16
17  {
18
19   "choice": "Python",
20
21   "votes": 1024
22
23  },
24
25  {
26
27   "choice": "Objective-C",
28
29   "votes": 512
30
31  },
32
33  {
34
35   "choice": "Ruby",
36
37   "votes": 256
38
39  }
40
41 ]
42
43}

The binding for our question attribute will be:

1{{ Data Provider.Rows.0.question }}

For our choices, we’re using:

1{{ Data Provider.Rows.0.choices.0.choice }}
2
3{{ Data Provider.Rows.0.choices.1.choice }}
4
5{{ Data Provider.Rows.0.choices.2.choice }}
6
7{{ Data Provider.Rows.0.choices.3.choice }}

Default value

We can then preview our app to confirm that this has worked.

Test

We’re almost done with this form, but we should also update our headline component with new display text.

img

The last thing we need to do is update our button action to populate our PUT query with our form data.

So, we’ll alter our existing button action to do this.

Button action

All of our existing bindings are still present.

Bindings

The last thing we need to do is assign a value to the id binding, using {{ URL.id }}.

URL id

While we’re here, we’ll create a second button action to navigate back to our home screen when a submission is made.

We can do the same thing on our other form screen, too.

Hmoescreen

Once again, we can preview our app to test that we’re sending form data to our API correctly.

Send form data to api

And we can confirm this in our API server’s admin panel.

API body

Now, we have two fully functional forms for sending data to our API.

4. Design tweaks and publishing

Before we wrap up, we’re going to make a few tweaks to our app’s UI.

First, under Navigation, we’ll hit Configure Links to set how we want each page to appear in our nav bar.

Nav

Then, under Screen and Theme, we’ll choose Darkest.

Darkest

Once we’re satisfied, we can hit Publish to push our app live.

Publish

Here’s a reminder of what our finished app looks like.

Send form data to API

If you found this guide helpful, check out our digital forms page to learn more about how Budibase empowers teams to build advanced forms on top of any data source.