Attachments

When you want to send files through the API, such as when using the Create draft or similar API endpoints, you must set the Content-Type HTTP header set to multipart/form-data. You then split the JSON data that you normally send in the request body into multiple form fields (one for each property) named after the property key.

Many but not all Core API endpoints support sending attachments. Refer to the Core API Reference documentation for details.

📘

Attachments are limited to 25 MB.

Basic example: make sure the Content-Type header is set to multipart/form-data

curl -X POST 'https://api2.frontapp.com/inboxes/inb_123/imported_messages' \
-H 'Authorization: Bearer API_TOKEN' \
-H 'Content-Type: multipart/form-data' \
--form 'external_id=123456abcdef' \
--form 'created_at=1619656054' \
--form 'attachments[]=@/Users/me/Photos/cat.jpg' \
import requests

url = "https://api2.frontapp.com/conversations/:conversation_id/comments"

headers = {
    'Authorization': f'Bearer {API_TOKEN}',
}

files = {
    'attachments': open('file.jpg', 'rb'),
    'body': (None, 'MESSAGE_BODY'),

}

response = requests.post(url, headers=headers, files=files)

"""

When passing the files parameter the requests library will automatically handle setting the appropriate 
Content-Type header to multipart/form-data.

Therefore, explicitly setting the Content-Type header to multipart/form-data is unnecessary
so it is not included in headers.

"""

Arrays in multipart form data

Some API body parameters must be sent as an array. For example, the to parameter or the attachments array itself. In these cases, you split the array into multiple form fields. For example, {"to": [[email protected], [email protected]]} would be split in two fields named to[][email protected] and to[][email protected]).

curl -X POST 'https://api2.frontapp.com/channels/FRONT_CHANNEL_ID/messages' \
-H 'Authorization: Bearer API_TOKEN' \
-H 'Content-Type: multipart/form-data' \
--form 'author_id=AUTHOR_ID' \
--form 'to[][email protected]' \
--form 'to[][email protected]' \
--form 'attachments[]=@/Users/me/Photos/cat.jpg' \
--form 'attachments[]=@/Users/me/Photos/dog.jpg' \
--form 'body=MESSAGE_BODY'
import requests

url = "https://api2.frontapp.com/channels/:channel_id/drafts"

headers = {
    'Authorization': f'Bearer {API_TOKEN}',
}

files = [
    ('author_id', (None, ':teammate_id')),
    ('to[]', (None, '[email protected]')),
    ('to[]', (None, '[email protected]')),
    ('attachments[]', open('alfredo.jpg', 'rb')),
    ('attachments[]', open('daisy.jpg', 'rb')),
    ('body', (None, 'A baby\'s gotta do what a baby\'s gotta do!')),
]

response = requests.post(url, headers=headers, files=files)

"""

When passing the files parameter the requests library will automatically handle setting the appropriate 
Content-Type header to multipart/form-data.

Therefore, explicitly setting the Content-Type header to multipart/form-data is unnecessary
so it is not included in headers.

"""

Nested objects in multipart form data

Some API body parameters are nested within objects, such as name and handle in the sender object:

"sender": {
  "name": "Lucy",
  "handle": "[email protected]"
}

In these cases, split the parameters into multiple form fields and use the syntax, objectName[propertyName] for the name of the form field. In our sender example, the fields would be named sender[handle] and sender[name].

curl -X POST 'https://api2.frontapp.com/inboxes/inb_123/imported_messages' \
-H 'Authorization: Bearer API_TOKEN' \
-H 'Content-Type: multipart/form-data' \
--form 'external_id=lj19hkjjlsd9893d' \
--form 'created_at=1619656054' \
--form 'sender[handle][email protected]' \
--form 'sender[name]=Lucy' \
--form 'metadata[is_inbound]=true' \
--form 'metadata[is_archived]=false' \
--form 'to[][email protected]' \
--form 'to[][email protected]' \
--form 'body=MESSAGE_BODY' \
--form 'attachments[]=@/Users/me/Photos/cat.jpg' \
--form 'attachments[]=@/Users/me/Photos/dog.jpg'
import requests

url = "https://api2.frontapp.com/inboxes/inb_123/imported_messages"


headers = {
    'Authorization': 'Bearer API_TOKEN',
}

files = [
    ('external_id', (None, 'lj19hkjjlsd9893d')),
    ('created_at', (None, '1619656054')),
    ('sender[handle]', (None, '[email protected]')),
    ('sender[name]', (None, 'Lucy')),
    ('metadata[is_inbound]', (None, 'true')),
    ('metadata[is_archived]', (None, 'false')),
    ('to[]', (None, '[email protected]')),
    ('to[]', (None, '[email protected]')),
    ('body', (None, 'MESSAGE_BODY')),
    ('attachments[]', open('/Users/me/Photos/cat.jpg', 'rb')),
    ('attachments[]', open('/Users/me/Photos/dog.jpg', 'rb')),
]

response = requests.post(url, headers=headers, files=files)

"""

When passing the files parameter the requests library will automatically handle setting the appropriate 
Content-Type header to multipart/form-data.

Therefore, explicitly setting the Content-Type header to multipart/form-data is unnecessary
so it is not included in headers.

"""

Node examples

The following provides an example for Node. We also have examples in GitHub for sending an attachment when creating a new message and for receiving messages in a custom channel.

const FRONT_API_TOKEN = 'YOUR FRONT API TOKEN GOES HERE';
const CHANNEL_ID = 'YOUR FRONT CHANNEL ID GOES HERE';

const FormData = require('form-data');
const fs = require('fs');

// abstract and promisify actual network request
async function makeRequest(formData, options) {
  return new Promise((resolve, reject) => {
    const req = formData.submit(options, (err, res) => {
      if (err)
        return reject(new Error(err.message))

      if (res.statusCode < 200 || res.statusCode > 299)
        return reject(new Error(`HTTP status code ${res.statusCode}`))

      const body = [];
      res.on('data', (chunk) => body.push(chunk));
      res.on('end', () => {
        const resString = Buffer.concat(body).toString();
        resolve(resString);
      })
    })
  })
}

const formData = new FormData()

// Set your data here: (See full options at https://dev.frontapp.com/reference/messages-1#post_channels-channel-id-messages)
formData.append('subject', 'Message subject');
formData.append('to[]', '[email protected]');
formData.append('to[]', '[email protected]');
formData.append('sender_name', 'Support');
formData.append('body', '<p>Message body</p>');
formData.append('attachments[]', fs.createReadStream('./photo.jpg'));

const options = {
  host: 'api2.frontapp.com',
  path: `/channels/${CHANNEL_ID}/messages`,
  method: 'POST',
  protocol: 'https:', // note : in the end
  headers: {
    Authorization: `Bearer ${FRONT_API_TOKEN}`
  },
}

async function run() {
  const res = await makeRequest(formData, options);
  console.log(res);
}

run()

Download an attachment from the API

For information about downloading attachments received in API responses, refer to the reference topic and the Download attachment endpoint.