Unable to call API - Invalid field type in multipart/form-data request

Hi there :wave: ,
I'm trying to integrate some endpoints from Paypal API. In particular I'm trying to submit evidence files along with some JSON data that needs to go with the payload as well.

According to their documentation request should be as follows:

curl -v -X POST https://api-m.sandbox.paypal.com/v1/customer/disputes/PP-D-27803/provide-supporting-info \
-H 'Authorization: Bearer A101.OLQiCxMmoVwigKQQDu3CYlamZ1KTKQmhrbAZK85RIy4IiWh9d_up_Nliuq_lfZdU.P3gvkY3PO28akjKYaDorm12QdfK' \
-H 'Content-Type: multipart/related; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'  \
-F 'input={"notes" : "Sample notes"};type=application/json'\
-F 'file1=@doc.pdf'

Note the type=application/json included in the field input.

While I was able to get this request working on Postman only I found out that there was a hidden option to set the content type of the field; see the image from below.

I wasn't able to set that field type from within HTTP resource type in Retool workflows, as the only to options that can be specified are Text or File.

Only after setting this option in Postman I was able to get a successful response.

Is there a way to do the same in the HTTP resource block either from the UI or by invoking it from code?

Thank you in advance!

I don't know if this will fix things or not, but the OpenAPI specs for Paypal are on Github here.

click the OpenAPI link for the API you want to use (disputes in your case it looks like)
image

then click 'RAW' in the top right-ish corner to view the file
image

now just copy everything in the address bar, in this case it's: https://raw.githubusercontent.com/paypal/paypal-rest-api-specifications/main/openapi/customer_disputes_v1.json

back in Retool, make a new resource using the OpenAPI type and paste that link as the Specification URL and fill out the Name and if you want Description fields. you can click Test Connection to make sure no authentication is needed

now you can select this as a resource query in you app or workflow like below

if you haven't noticed yet, not only do you get dev comments/documentation but ALL the endpoints are already generated and with proper types. the OpenAPI spec should make sure everything is filled out and formatted properly keeping you from needing to mess w fetch() or whatever.
image

I managed to put off playing around with resource types other than the REST one until literally today and I 100% regret it :upside_down_face: :rofl:. If, however, you still really want to do this in pure JS feel free to let me know and I'll see if I can get something working for you

Thanks for the reference, didn't know about and it has lots of potential. I will consider using it next time.

This time however, the API definition doesn't seem to be complete. In particular, the /provide-evidence endpoint has missing fields and is not allowing me to set both: a file and a JSON string but only the file.

Just for reference, I was able to replicate the request from a code node:

var request = require('request');
var fileBuffer = Buffer.from(jsGenerateFile.data?.[0]?.data, 'base64');
var options = {
  'method': 'POST',
  'url': 'https://api-m.sandbox.paypal.com/v1/customer/disputes/PP-R-XLD-10095231/provide-supporting-info',
  'headers': {
    'Authorization': 'Bearer <token>'
  },
  formData: {
    'evidence-file': {
      'value': fileBuffer,
      'options': {
        'filename': 'Refund & Chargeback Policies.pdf',
        'contentType': 'application/pdf'
      }
    },
    'input': {
      'value': '{"notes": "Sample Notes"}',
      'options': {
        'contentType': 'application/json' // THIS IS WHAT MAKES IT TO WORK
      }
    }
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

However, in this approach I'm not able to take advantage of Environment-based variables for API credentials i.e.

how odd, I wonder what made them make that design decision. you should def consider marking your post as the solution though, I'm sure you're not the only one to come across this

Retool Support just pointed me out to this related thread.

I just followed same idea and built the request body from scratch in a code node.

return `
--__________boundary__________
Content-Disposition: related; name="input"
Content-Type: application/json

{"notes": "Sample Notes 5"}
--__________boundary__________
Content-Disposition: related; name="evidence-file"; filename="Testing document.pdf"
Content-Type: application/pdf
Content-Transfer-Encoding: base64

${jsGenerateFile.data?.[0]?.data}
--__________boundary__________--`

Then on the actual dedicated Paypal resource node:

And I finally received a successful response.

1 Like