# Upload Attachment

Use an Upload Attachment node in your Flow to attach one or more files to a record of the specified Object Type. Files can come from a browser multipart form upload, an email attachment payload, or any binary buffer available in your flow. To configure an Upload Attachment node in the Flow Editor, drag it from the Palette to the Workspace canvas, then double-click the node to open and configure its behavior.

{% stepper %}
{% step %}

### Provide an optional **Name** for the node.

By default an Upload Attachment node will be shown with a label of "upload attachment", but the value you provide in the Name field will replace it in the Flow Editor UI making your flow easier to read and understand.
{% endstep %}

{% step %}

### Select a **Type Id** for the node — the Object Type that has Records with which you want to use attachments, specified using one of several options.

* *type* - choose this option for a dropdown that includes the Display Names of the Object Types you have created in your Contextual tenant.
* *string* - choose the string option, and type in a string for the Object Type ID, using *type* is recommended instead of string
* *msg.* - choose this option to specify a path in the msg. object that contains the Object Type ID value, e.g. `msg.payload.thePropertyWithTheObjectTypeId`
* *env variable* - Environmental Variables are a feature of Agents in Contextual. Any Environmental Variables that you define as Label/Value pairs for an Agent that is sending events to a Flow, will be available to the Flow, simply type the Label of the Environmental Variable from which you want to use the value.
  {% endstep %}

{% step %}

### Specify the **Object Id** of the record you want to attach the file(s) to.

* Use *string or* *msg.*
* This is typically the ID of a record you have previously created or retrieved earlier in your flow, e.g. `msg.createResponse.id`
  {% endstep %}

{% step %}

### Specify the **Property** — the msg. object path that contains the file or files to upload.

* For browser multipart form uploads, this is typically `msg.req.files`
* For email attachment arrays (e.g. from a Postmark webhook payload), this is typically `msg.payload.Attachments`
* For a single file buffer, this is typically `msg.payload`
* The node accepts arrays, single objects, or nested objects in any of the following shapes:
  * **Standard:** `{ filename, content, contentType?, size? }`
  * **Multer-style** (Express/Multer `req.files`): `{ originalname, buffer, mimetype?, size? }`
  * **Postmark-style:** `{ Name, Content, ContentType?, ContentLength? }`
    {% endstep %}

{% step %}

### Specify the **Output** msg. object path to store the array of created attachment objects, e.g. `msg.payload`.

{% endstep %}

{% step %}

### Optionally configure **Parallelism** if your flow is uploading attachments across multiple concurrent execution paths.

* *none* — default; upload operations proceed sequentially
* When parallelism is configured, set a **Max Parallelism** value to cap the number of concurrent upload operations
  {% endstep %}
  {% endstepper %}

When the Upload Attachment node is included in the path of your flow, it will upload the file(s) from the specified property and attach them to the specified record.

## Example: Browser Multipart Upload

The following pattern accepts a multipart form `POST`, creates a record, then attaches the uploaded files to it using an Upload Attachment node.

```javascript
// Function node — build the record payload before Create Object
msg.createPayload = {                                                                                                                                                           
    name: msg.req.body.name                                                                                                                                                       
  }                                                         
return msg  
```

After a Create Object node writes the new record ID to `msg.createResponse`, configure the Upload Attachment node with:

* **Object Id:** `msg.createResponse.id`
* **Property:** `msg.req.files`

## Example: Email Attachment Upload

When receiving email via a Postmark webhook (`POST /postmark`), the parsed attachments array is available at `msg.payload.Attachments`. Configure the Upload Attachment node with:

* **Object Id:** `msg.createResponse.id`
* **Property:** `msg.payload.Attachments`

To also store the original email as an `.eml` file, chain a second Upload Attachment node after normalizing the raw email into a buffer:

```javascript
// Function node — build the .eml buffer from the raw email body
const normalizedEml = msg.payload.RawEmail.replace(/\r?\n/g, '\r\n')
const emlBuffer = Buffer.from(normalizedEml, 'utf8')

msg.payload = {
  filename: `${msg.payload.Subject}.eml`,
  content: emlBuffer,
  contentType: 'message/rfc822',
  size: emlBuffer.length,
}
return msg
```

Configure the second Upload Attachment node with:

* **Object Id:** `msg.createResponse.id`
* **Property:** `msg.payload`
