Skip to content

Instantly share code, notes, and snippets.

@hdornier
Last active January 29, 2024 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hdornier/e04d04921032e98271f46ff8a539a4cb to your computer and use it in GitHub Desktop.
Save hdornier/e04d04921032e98271f46ff8a539a4cb to your computer and use it in GitHub Desktop.
Front API Attachment Example

When you want to send files through the API, your request needs to be sent using the Content-Type HTTP header set to multipart/form-data. The JSON data you would normally send in the request body needs to be split in multiple form fields (one for each property) named after the property key. If the property is an array, the name should include the index of the data (ie: {"to": [email1@example.com, email1@example.com]} would be split in two fields named to[0], to[1]).

Below is an example template demonstrating how to send a message via Front's Create conversation API endpoint:

curl -X POST 'https://api2.frontapp.com/channels/FRONT_CHANNEL_ID/messages' \
-H 'Authorization: Bearer YOUR_FRONT_API_TOKEN' \
-H 'Content-Type: multipart/form-data' \
--form 'author_id=AUTHOR_ID' \
--form 'to[0]=RECIPIENT_HANDLE' \
--form 'attachments=@PATH_TO_FILE' \
--form 'body=MESSAGE_BODY'

For a practical example, below you can see an example where the VARIABLES have been populated with example values:

curl -X POST 'https://api2.frontapp.com/channels/cha_123/messages' \
-H 'Authorization: Bearer 7ihw3d73wi7ehfw84...' \
-H 'Content-Type: multipart/form-data' \
--form 'author_id=tea_123' \
--form 'to[0]=+14155550000' \
--form 'attachments=@/Users/me/Photos/cat.jpg' \
--form 'body=This is an SMS message with an attached photo of a cat'

The following provides an example for Node:

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[0]', 'recipient@example.com');
formData.append('to[1]', 'recipient2@example.com');
formData.append('sender_name', 'Support');
formData.append('body', '<p>Message body</p>');
formData.append('attachments[0]', 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()
@Passer-Keenan
Copy link

Passer-Keenan commented Aug 16, 2023

Was attempting to do this in Python and was running into a couple issues with the main points being:

  • Do not manually set the Content-Type header due to issues
  • Move the list of files you are including into the files parameter in your request
  • Ensure you are passing the parameter data and not json

Here is an example:

def draft_with_attachments(data: dict, files: dict):
    resp = requests.post(
        f"{FRON_URL}/channels/{channel_id}/drafts",
        headers={
            "Accept": "application/json",
            "Authorization": f"Bearer {API_TOKEN}",
        },
        data=data, # Should NOT be json=...
        files=files,
)


# attachments is a list of decoded files
def draft_a_new_email(subject: str, message_body: str, author: str, attachments: list, sending_to: list):
    files = {}
    to_emails = {}
    for ind, attachment in enumerate(attachments):
        files[f"attachments[{ind}]"] = attachment["contents"]
    for ind, email in enumerate(sending_to):
        to_emails[f"to[{ind}]"] = email
    
    data={
        "body": message_body,
        "author_id": author,
        "subject": subject,
    }
    data.update(to_emails)
    draft_with_attachments(data, files)
    

@klapperkopp
Copy link

What's the limitation on file types and file sizes for attachments? I cannot find it anywhere.

@dugjason
Copy link

What's the limitation on file types and file sizes for attachments?

Max attachment size varies on a per-channel basis. Documented here: https://help.front.com/en/articles/2158
Most image / PDF / document file types are accepted (Word / Excel / MP4 etc).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment