Creating Body for POST API request

Hi,
I want to create a query to send a POST request.
The body structure I need is as follows:

REQUEST BODY SCHEMA has to be application/json

How should I form the body in Retool in the right format?

Hi @mondob,

This is a weird one in terms of why it's implemented by Retool like this in the first place, but just change that first option in the Body from JSON to raw and then you can paste in text as needed, just like in your Postman screenshot.

Thanks for the replay @MikeCB

This is just an example that I used to show what I need, but actually, I will use data from my Retool query data. This is the actual data I want to POST.

When I select raw in Postman it also returns error, so I guess I can't use raw, as it only works when the body is set to JSON.

Hi @mondob,

If the screenshot in your first post from Postman is working, then what you've got in that last example is close, but not quite the same. Because you're sending an array of data objects, you'd still need to set it to raw and create your array based on your needs. Even if you're only doing a single data object, you'd still need to wrap it in [] to turn it into an array.

What you want your payload to be is:

[
  {
    data: {
      76560: {{exportFile.data.company_name}},
      795653: {{exportFile.data.vat_number}}
    }
  }
]

The square brackets wrapping it are likely what you're missing - can't say for sure without the API docs, but that's the difference I can see between your Postman example and your screenshot.

If you needed to send multiple data objects, you'd just add them to the array, something like this:

[
  {
    data: {
      76560: {{exportFile.data.company_name}},
      795653: {{exportFile.data.vat_number}}
    }
  },
  {
    data: { 
      76561: {{exportFile.data.company_name}},
      795654: {{exportFile.data.vat_number}}
    }
  }
]

You'd probably want to build the array in a separate function to map over the data if you're doing multiple so it builds them out. Right now it looks like exportFile.data is a single object, in which case you don't have to worry about multiple, but you probably still need to format it into an array.

@MikeCB,
Yes, I think [] might be the problem. However, when the body is set to raw and I send a request with the following body it still returns bad request error.

[
  {
    data: {
      76560: {{exportFile.data.company_name}},
      79563: {{exportFile.data.vat_number}}
    }
  }
]

This is API documentation with requirements - Adversus API documentation

It says:

Inserts contacts by submitting an array of objects where each object has a data property with a key value representation of the contacts data.

I also think that it might not work because content type must be application/json :thinking:

In my case exportFile.data might have one or more rows.

@mondob,

Yes, that's right, if you use raw you'll need to manually add a header for content-type: application/json to the headers section of your request.

Can you share an example of what the data would look like (change the values!) when exportFile.data contains multiple rows? You can probably build a helper function / block after getting the data to turn it into the POST body you need.

@MikeCB ,
I added content-type to header but now I get a 403 error - "Forbidden".
This is weird because I have all the permissions needed.

My data looks like this:

.

Hi @mondob,

I can't speak to the 403, but does your request now look more (or exactly) like the one in Postman? Do you have a function that converts that exportFile.data to the format you need?

In your example, your payload looks like this:

[
  {
    data: {
      76560: {{exportFile.data.company_name}},
      79563: {{exportFile.data.vat_number}}
    }
  }
]

But {{exportFile.data.company_name}} is an array of data, you'd need it to be {{exportFile.data.company_name[0]}} to include the first item in the array.

Assuming that data mean you have 2 rows, you'd need to reshape the data. Maybe a new node after you get export data that does something along the lines of this:

const newData = exportFile.data.companyName.map((company, index) => {
  const row = { 
                data: { 
                  76560: company,
                  76561: exportFile.data.vat_number[index]
               }
  return row
})
return newData

That should generate the data in the format you need, so if this block was called shapedData you could put {{shapedData.body}} in the raw body of your POST call.

For what it's worth, I'm just using company in the object because we're mapping over it so it's there, you could access it via the index just like the vat_number, it's just quick way to map over the "rows" of data.

1 Like

Thanks, @MikeCB, this works :pray:

1 Like