How to interpret this doc fragment about creating a file

 /**
     * Operation createFile
     *
     * Create a file
     *
     * @param  string $file File to upload. This is a file sent as multi-part (not a string) (required)

I’m wondering what the phrase "This is a file sent as multi-part (not a string)" means in the context of the parameter’s declared type.

Thanks for any insight.

Hi @Jeffrey_Chimene. That phrase means the $file parameter expects an actual file upload (binary data), not a plain text string. The request must use multipart/form-data, with the file attached as a separate part of the form rather than embedded as JSON or raw text.

Here’s a working cURL example:

curl --location ‘https://api.infusionsoft.com/crm/rest/v2/files
–header ‘Authorization: Bearer <YOUR_TOKEN>’
–header ‘Accept: application/json’
-F ‘file=@/path/to/samplelogo.png’
-F ‘file_name=“samplelogo.png”;type=application/json’
-F ‘file_association=“"CONTACT"”;type=application/json’
-F ‘is_public=“false”;type=application/json’
-F ‘contact_id=“4085”;type=application/json’

1 Like

@OmarAlmonte
This still isn’t working. I’ll step through the FilesAPI to assess the relationship between the REST APi & the PHP API. While doing so, I came accross this code in Api/FilesAPI.php

 $formParams = $formDataProcessor->flatten($formData);
 $multipart = $formDataProcessor->has_file;
 $multipart = true;

in the generated api/FilesApi.php
So the flag is forced True, even though the FormDataProcessor didn’t encode the file. I’ll look into that.

The FormDataProcessor isn’t seeing the filespec that’s being sent into the routine. I deleted my earlier post as this filespec had a bad path, and couldn’t be located. After correcting that error, I’m still not able to get the FormProcessor to encode the intended file.

Yeah, I’m not seeing how your object serializer handles reading a file. It looks like you want the file contents, not the file path. The next question, of course, is it supposed to be base64 encoded? I guess we’ll find out in the next episode.

It’s still an opaque error 500 from the server after sending base64 encoded file contents. At least the multipart stull is correctly generated for the HTTP POST

Unless someone can confirm that this works, it would appear that there is a bug of some kind.

When using Postman I can get back a 400 or a 500 response code.

Request:
curl --location ‘``https://api.infusionsoft.com/crm/rest/v2/files’``
–header ‘Authorization: Bearer KeapAK-SAK_KEY’
–header ‘Cookie: removed’
–form ‘contact_id=“6”’
–form ‘file_association=“CONTACT”’
–form ‘file_name=“TestImg.png”’
–form ‘is_public=“false”’
–form ‘file=@“/C:/Users/Owner/Documents/TestImg.png”’

400 Response:
{
“code”: 400,
“message”: “Content-Type ‘application/octet-stream’ is not supported”,
“status”: “Bad Request”,
“details”: [
{
“domain”: “file”,
“resource”: “POST /rest/v2/files”
}
]
}

If I explicitly set the multipart header I get the 500 (presumably because there’s no boundary associated with it)

Request:
curl --location ‘``https://api.infusionsoft.com/crm/rest/v2/files’``
–header ‘Accept: application/json’
–header ‘Content-Type: multipart/form-data’
–header ‘Authorization: Bearer KeapAK-SAK_KEY’
–header ‘Cookie: removed’
–form ‘contact_id=“6”’
–form ‘file_association=“CONTACT”’
–form ‘file_name=“TestImg.png”’
–form ‘is_public=“false”’
–form ‘file=@“/C:/Users/Owner/Documents/TestImg.png”’

500 Error Stack Trace
`org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request
org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:133)
org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:112)
org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:88)
org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:112)
org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1228)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
com.infusionsoft.utils.servlet.BaseJspFilter.doFilter(BaseJspFilter.java:84)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:362)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:278)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

Caused by:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.init(FileItemIteratorImpl.java:189)
org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.getMultiPartStream(FileItemIteratorImpl.java:206)
org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.findNextItem(FileItemIteratorImpl.java:225)
org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.(FileItemIteratorImpl.java:142)
org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:303)
org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:452)
org.apache.catalina.connector.Request.parseParts(Request.java:2675)
org.apache.catalina.connector.Request.parseParameters(Request.java:3029)
org.apache.catalina.connector.Request.getParameter(Request.java:1109)
org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:306)
com.infusionsoft.spa.utils.SpaLocalDevFilter.doFilterInternal(SpaLocalDevFilter.java:20)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:186)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
com.infusionsoft.headers.RequestHeaderFilter.doFilterInternal(RequestHeaderFilter.java:36)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)`

@Jeffrey_Chimene I was able to identify the root cause of the issue.

For now, as a workaround, I created a small helper class. This ensures the multipart request is formatted exactly the way the API expects, and it’s working consistently.

Here’s the helper:

<?php
  namespace Keap\Helpers;

  use GuzzleHttp\Client;
  use GuzzleHttp\Exception\RequestException;

  class FileUploadHelper
  {
      private Client $client;
      private string $accessToken;
      private string $baseUrl;

      public function __construct(string $accessToken, string $baseUrl = 'https://api.infusionsoft.com/crm/rest')
      {
          $this->client = new Client();
          $this->accessToken = $accessToken;
          $this->baseUrl = rtrim($baseUrl, '/');
      }

      public function uploadFile(
          string $filePath,
          string $fileAssociation,
          bool $isPublic = false,
          ?string $contactId = null,
          ?string $fileName = null
      ): array {
          if (!file_exists($filePath)) {
              throw new \Exception("File not found: {$filePath}");
          }

          $filePath = realpath($filePath);
          if ($fileName === null) {
              $fileName = basename($filePath);
          }
          $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';

          $multipart = [
              [
                  'name' => 'file',
                  'contents' => fopen($filePath, 'r'),
                  'filename' => basename($filePath),
                  'headers' => ['Content-Type' => $mimeType]
              ],
              [
                  'name' => 'file_name',
                  'contents' => $fileName,  // Plain string
                  'headers' => ['Content-Type' => 'application/json']
              ],
              [
                  'name' => 'file_association',
                  'contents' => json_encode($fileAssociation),  // JSON string: "CONTACT"
                  'headers' => ['Content-Type' => 'application/json']
              ],
              [
                  'name' => 'is_public',
                  'contents' => $isPublic ? 'true' : 'false',  // JSON boolean
                  'headers' => ['Content-Type' => 'application/json']
              ]
          ];

          if ($contactId !== null) {
              $multipart[] = [
                  'name' => 'contact_id',
                  'contents' => $contactId,  // JSON number
                  'headers' => ['Content-Type' => 'application/json']
              ];
          }

          try {
              $response = $this->client->request('POST', "{$this->baseUrl}/v2/files", [
                  'headers' => [
                      'Authorization' => "Bearer {$this->accessToken}",
                      'Accept' => 'application/json'
                  ],
                  'multipart' => $multipart
              ]);
              return json_decode($response->getBody()->getContents(), true) ?? [];
          } catch (RequestException $e) {
              $statusCode = $e->getResponse() ? $e->getResponse()->getStatusCode() : 0;
              $responseBody = $e->getResponse() ? $e->getResponse()->getBody()->getContents() : '';
              throw new \Exception("File upload failed [{$statusCode}]: {$responseBody}");
          }
      }
  }

Usage example:

$helper = new FileUploadHelper($accessToken);

  $result = $helper->uploadFile(
      filePath: '/path/to/image.png',
      fileAssociation: 'CONTACT',
      isPublic: false,
      contactId: '12345',
      fileName: 'my_file.png'
  );

  echo "Uploaded: " . $result['id'];

I’ll bring up the SDK issue internally.

1 Like

@Marion_Dorsett2 I’d double-check that you’re sending the correct Content-Type header in Postman. Here’s another cURL example you can try:

@OmarAlmonte
Still getting the error 500
It looks like there’s still something not quite right in the API POST
here is $multipart

array (
  0 => 
  array (
    name => 'file',
    contents => resource id='1460' type='stream',
    filename => 'sampleFile.dat',
    headers => 
    array (
      Content-Type => 'text/plain',
    ),
  ),
  1 => 
  array (
    name => 'file_name',
    contents => 'sampleFile.dat',
    headers => 
    array (
      Content-Type => 'application/json',
    ),
  ),
  2 => 
  array (
    name => 'file_association',
    contents => '"CONTACT"',
    headers => 
    array (
      Content-Type => 'application/json',
    ),
  ),
  3 => 
  array (
    name => 'is_public',
    contents => 'false',
    headers => 
    array (
      Content-Type => 'application/json',
    ),
  ),
  4 => 
  array (
    name => 'contact_id',
    contents => '43185',
    headers => 
    array (
      Content-Type => 'application/json',
    ),
  ),
)

Here is the POST body

[22-Feb-2026 17:32:51 UTC] Fred [DEBUG]: --14c1ae591369ce203a720abf2cbba851af2c82a1
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--14c1ae591369ce203a720abf2cbba851af2c82a1
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 14

sampleFile.dat
--14c1ae591369ce203a720abf2cbba851af2c82a1
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

"CONTACT"
--14c1ae591369ce203a720abf2cbba851af2c82a1
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--14c1ae591369ce203a720abf2cbba851af2c82a1
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 5

43203
--14c1ae591369ce203a720abf2cbba851af2c82a1--

@Jeffrey_Chimene The issue is with file_name and contact_id, they need to be valid JSON values since you’re declaring Content-Type: application/json for those parts.

file_name is being sent as sampleFile.dat (plain text), but the API expects a JSON string: "sampleFile.dat" (with quotes). Same thing with contact_id, it should be "43185" instead of just 43185.

Try wrapping those values with json_encode():

$multipart = [
    [
        'name'     => 'file',
        'contents' => fopen($filePath, 'r'),
        'filename' => basename($filePath),
        'headers'  => ['Content-Type' => $mimeType]
    ],
    [
        'name'     => 'file_name',
        'contents' => json_encode($fileName),       // "sampleFile.dat"
        'headers'  => ['Content-Type' => 'application/json']
    ],
    [
        'name'     => 'file_association',
        'contents' => json_encode($fileAssociation), // "CONTACT"
        'headers'  => ['Content-Type' => 'application/json']
    ],
    [
        'name'     => 'is_public',
        'contents' => $isPublic ? 'true' : 'false',
        'headers'  => ['Content-Type' => 'application/json']
    ],
    [
        'name'     => 'contact_id',
        'contents' => json_encode($contactId),       // "43185"
        'headers'  => ['Content-Type' => 'application/json']
    ]
];

Let me know if that resolves the 500 error.

Hi @OmarAlmonte

That gives a different error, so I’m getting closer. Here is the current $multipart initialization:

        $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';

        $multipart = [
            [
                'name' => 'file',
                'contents' => fopen($filePath, 'r'),
                'filename' => basename($filePath),
                'headers' => ['Content-Type' => $mimeType]
            ],
            [
                'name' => 'file_name',
                'contents' => json_encode($fileName),  // Plain string
                'headers' => ['Content-Type' => 'application/json']
            ],
            [
                'name' => 'file_association',
                'contents' => json_encode($fileAssociation),  // JSON string: "CONTACT"
                'headers' => ['Content-Type' => 'application/json']
            ],
            [
                'name' => 'is_public',
                'contents' => $isPublic ? 'true' : 'false',  // JSON boolean
                'headers' => ['Content-Type' => 'application/json']
            ]
        ];

        if ($contactId !== null) {
            $multipart[] = [
                'name' => 'contact_id',
                'contents' => \json_encode($contactId),  // JSON number
                'headers' => ['Content-Type' => 'application/json']
            ];
        }

Here is the generated body:

--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 16

"sampleFile.dat"
--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

"CONTACT"
--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 7

"43205"
--1bb3679170a1f1da5ea0c2324359d1a15e7b7d4e--

The contact exists, nevertheless, the error is:

{"code":400,"message":"contact_id is invalid","status":"Bad Request","details":[{"domain":"file","resource":"POST /rest/v2/files"}]}

@Jeffrey_Chimene Looking at your POST body, the file_association value is being sent as "CONTACT" (with literal quotes) instead of just CONTACT.
Your body shows:

Content-Length: 9
"CONTACT"

If it were correct, it should be:

Content-Length: 7
CONTACT

In your $multipart array, change:
```php
// Current
'contents' => '"CONTACT"'

// Fix
'contents' => 'CONTACT'

Let me know if that fixes it.

@OmarAlmonte That just gives a JSON parse error:

--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 16

"sampleFile.dat"
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

'CONTACT'
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 7

"43229"
--4297626f6233d5abb188b4918f3e3e24d703d052--

Here’s the error. I tried changing the mimetype to “text/plain”, and omitting the quotes, but that mimetype is not supported.

{"code":400,"message":"JSON parse error: Unexpected character (''' (code 39)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')","status":"Bad Request","details":[{"domain":"file","resource":"POST /rest/v2/files"}]}

Sending a value like "'CONTACT'"
yielded

{"code":400,"message":"Input value is invalid: 'CONTACT'","status":"Bad Request","details":[{"domain":"file","resource":"POST /rest/v2/files"}]}

@Jeffrey_Chimene - You need to remove the quotes around ‘CONTACT’.

1 Like

@Pav
I’ve already done that. It doesn’t work with the mimetype application/json
Here’s the generated multipart body:

--88eb6c786c60301c9247632cc518d2c5e905cceb
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 7

"43255"
--88eb6c786c60301c9247632cc518d2c5e905cceb
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--88eb6c786c60301c9247632cc518d2c5e905cceb
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 16

"sampleFile.dat"
--88eb6c786c60301c9247632cc518d2c5e905cceb
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 7

CONTACT
--88eb6c786c60301c9247632cc518d2c5e905cceb
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--88eb6c786c60301c9247632cc518d2c5e905cceb--

Here’s the error:

{"code":400,"message":"JSON parse error: Unrecognized token 'CONTACT': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')","status":"Bad Request","details":[{"domain":"file","resource":"POST /rest/v2/files"}]}

I’ve tried changing the mimetype to text/plain; which mimetype is not supported for that value.
Single quote instead of double quote is not a valid quote character for application/json

@OmarAlmonte
It’s a burdensome requirement to dump Curl debugging info using this API. It was straightforward to implement network tracing ginen the FileUploadHelper call to client->Request. Trying to wire this same Guzzle middleware code into Api/Contact.php takes more effort than it should.

I see it is doing JSON checking. So you do need the double quotes around the “CONTACT” name.

I think the issue is that the Contact ID has double quotes, where it should be a pure number.

I have not tested this out, but try the following below.

--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 16

"sampleFile.dat"
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

"CONTACT"
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--4297626f6233d5abb188b4918f3e3e24d703d052
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 5

43229
--4297626f6233d5abb188b4918f3e3e24d703d052--

Already tested json_encode((int)$contact_id) thus dropping the quotes
no joy

@Jeffrey_Chimene,

Here’s an example I put together that is fully working so you can review it and use:

OK, I’ll take a look. I don’t see any difference that will make it work.

@OmarAlmonte
I’ve looked and used the code you supplied earlier.
The only difference I can see from the git project and my code is that your example searches for a contact. The test I use creates a contact, then tries to upload a file. I have no doubt your code uploads a file. You would not have posted a response otherwise.
I will take your example, and modify it to create a contact rather than using an existing contact.
FWIW, I added a 3ns delay after creating the contact to see if there was a server issue. That did not solve the problem.

File not created: Could not upload file
File upload failed [500]: {"code":500,"message":"There was a problem creating or updating the file","status":"Internal Server Error","details":[{"domain":"file","resource":"POST /rest/v2/files"}]}

I don’t see anything in the Troubleshooting section that addresses the Error 500 response.

--66b308d891fb810f34ac7674b3b381e9ba24dc19
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--66b308d891fb810f34ac7674b3b381e9ba24dc19
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 14

sampleFile.dat
--66b308d891fb810f34ac7674b3b381e9ba24dc19
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

"CONTACT"
--66b308d891fb810f34ac7674b3b381e9ba24dc19
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--66b308d891fb810f34ac7674b3b381e9ba24dc19
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 5

43523
--66b308d891fb810f34ac7674b3b381e9ba24dc19--

Looks like pilot error

1) systasisgfifscrm\TestFileUpload::testFileUpload10
Test code or tested code printed unexpected output:    File: sampleFile.dat (13 bytes)
   SUCCESS!
   - File ID: 8803
   - File Name: sample.zip
   - File Size: 13 bytes

3. Getting file details...
   - ID: 8803
   - Name: sample.zip
   - Category: DOCUMENTS
   - Contact ID: 43533

4. Deleting file (cleanup)...
   Deleted successfully!

I’m not sure what the difference is, as the cargo looks the same. Anyway, thanks for the solution!

--f25f41f0d2340224f793f319c658ef6722de1435
Content-Type: text/plain
Content-Disposition: form-data; name="file"; filename="sampleFile.dat"
Content-Length: 13

Hello, World!
--f25f41f0d2340224f793f319c658ef6722de1435
Content-Type: application/json
Content-Disposition: form-data; name="file_name"
Content-Length: 10

sample.zip
--f25f41f0d2340224f793f319c658ef6722de1435
Content-Type: application/json
Content-Disposition: form-data; name="file_association"
Content-Length: 9

"CONTACT"
--f25f41f0d2340224f793f319c658ef6722de1435
Content-Type: application/json
Content-Disposition: form-data; name="is_public"
Content-Length: 5

false
--f25f41f0d2340224f793f319c658ef6722de1435
Content-Type: application/json
Content-Disposition: form-data; name="contact_id"
Content-Length: 5

43533
--f25f41f0d2340224f793f319c658ef6722de1435--

@OmarAlmonte
This particular 500 error is a unsupported file type for $fileName. In this test, the file type is “.dat”; which is not a supported file type. When I switch the file type to “.zip”, there is joy.
I don’t see anything at the Rest API docs that indicates which file types are supported.
It might help debugging to pass the underlying error reason to the client.