Invoking a series of REST-api calls, collecting data from them to make a final REST-api call

I need to invoke 2 REST-api calls, extract returned information and then use that in the 3rd API call.

I searched through the forums and found that in order to do this -- the approach being recommended is to write a javascript snippet. I am a programming newbie (have done lots of coding in C).

In order to ensure that I was running things correctly; I first created the 3rd query using the web-retools-interface and ran it with dummy parameters. It worked but I had to configure "Content-Type" of application/json in headers and body-type of JSON (it does not work without that).

In order to see if I was scripting things correctly -- I wrote the following snippet and connected it to the form1=>submit button as a javascript query called form1SubmitHandler.

var p0=textInput4.value
var p1=textInput5.setValue
var p2=textInput6.value
var p3=textInput7.value
var p4=textInput8.value
var p5=date1.value
query15.trigger({
additionalScope:{p0:p0, p1:p1, p2:p2, ;3:p3, p4:p4,p5:p5}
});
var savedval=data[0].xxxxx

Next I filled unique values for the various text-input fields and clicked "submit".
Both form1SubmitHandler and query15 run silently but produce NO output. Query15 should have produced an output showing the output of the REST api -- it produces nothing.

Can someone point me to a example showing multiple REST-api calls being made and how values returned by the 1st call are used in subsequent calls? I have searched for this and found nothing.

Workflows would be a good option here.
They can have multiple steps, and I find organising the logic for nested/dependent calls like this much easier to reason about in a workflow. You can trigger a workflow from your app, and use its response in other components.

.trigger() returns a promise. if you have code after calling it that depends on the response don't forget to use await

const response = await query15.trigger({
additionalScope:{p0:p0, p1:p1, p2:p2, ;3:p3, p4:p4,p5:p5}
});
const r_data = response.data;

Thank you for your inputs bobthebear and hansontools for your prompt responses!

bobthebear - your input showing how to use the return value was especially educational. Thank you!

However, I resolved the issue differently; instead of trying to invoke multiple APIs, I worked with my backend developer and created new endpoint that accepts a multipart/form-data upload.

The following curl command now works from the terminal:
curl ${curl_opts} -X POST -H "Content-Type: multipart/form-data"
-F "f1filename=f1.pdf;type=application/text"
-F "f1file=@f1.pdf;type=application/octet-stream"
-F "f2filename=f2.pdf;type=application/text"
-F "f2file=@f2.pdf;type=application/octet-stream"
-F "project=@Project.json;type=application/json"
https://serverurl/xyz

However, when I code the same using the following for BODY:
f1filename: Text: {{ fileButton1.value[0].name }}
f2filename: Text: {{ fileButton2.value[0].name }}
f1file: File: {{ fileButton1.value[0].base64Data }}
f2file: File: {{ fileButton2.value[0].base64Data }}

I get a 415 error:
{"status":415,"message":"","timestamp":1716952115531,"error":"Unsupported Media Type","path":"xyz"}

I have tried different things for the f1file and f2file parameters:
a. sending text files and pdf files
b. converting it to ASCII [using btoa(fileButton1.value[0].base64Data)]
c. Sending fileButton1.value[0] (as was suggested on this page (Perform REST API requests | Retool Docs)

I get the same error (415) each time.

Thank you - in anticipation - for your help!

Are you setting the body to "Form Data" in your API setup?
image

Also, if you send additional information as part of the file key, what is the endpoint doing with it? The fileButton.value object has five keys: name, type, sizeBytes, and url (docs here).

if @jg80's suggestion doesn't fix it, could we see the resource query or the actual request being sent (don't forget to use paint or something to cover up any sensitive info)? you might need to use "Binary" or "Raw" instead of "Form Data", if I had to guess it seems like the problem is coming from a type mis-match with the 'Content-Type' header and the declared file type property 'application/octet-stream' (binary stream) while using the base64 data (string) in the body. you could try using "Binary", "f2file=@f2.pdf;encoder=base64" and {{ fileButton1.value[0].base64Data }}

jg80 and bobthebear:

I have attached the form-data that I am using.

I am not initializing any header nor using a URL parameters. My API expects a multipart data comprising of:
a) JSON structure (1st parameter)
b) 2 files [I am passing the base64Data field of fileButtonX.value[0]; I have tried sending this as-is AND tried sending as plain-text using btoa(fileButtonX.value[0].base64Data) -- neither works]

the fact that the 2nd parameter is of type file -- does that imply a type of application/octet-stream? If not, that may be the reason I am getting a 415 error (unsupported media type).

However, I see no way of setting that information in the API call and (I may be showing my ignorance here) how do I say that the 1st parameter is application/json and 2nd parameter is application/octet-stream?

Or does is it that I cannot mix the two?

For the files, have you tried sending an object with two keys? Something like:

{{
  {
    "data": fileButtonX.value[0].base64Data, // or btoa(fileButtonX.value[0].base64Data)
    "type": fileButtonX.value[0].type        // or "application/octet-stream"
  } 
}}

@bobthebear might be on the right track with switching away from the form; maybe a raw body of the form

{
  "f1filename": "f1.pdf",
  "f1file": {
    "data": "base64-encoded-content-of-f1.pdf",
    "type": "application/octet-stream"
  },
  "f2filename": "f2.pdf",
  "f2file": {
    "data": "base64-encoded-content-of-f2.pdf",
    "type": "application/octet-stream"
  },
  "project": {
    "someKey": { ... },
    "type": "application/json"
  }
}

Can your backed developer send you what she is receiving and what is expected?

1 Like

ya your header is telling the server it is going to send a bunch of 0s and 1s that represents an octet-stream but what your sending is a base64 encoded string.

Folks -- thank you for the responses. I will try that in a bit.
We did something different today morning -- since our files are known to be small -- I just passed the base64 string in the JSON. It worked for now and we are past our hiccup.
Will come back to this solution next week and try the above fix.

Thank you for quick generous help! Much appreciated!!

-p