# Handle Multipart Requests

A multipart request carries form fields and files in a single HTTP body using `multipart/form-data`. Hookdeck accepts these requests at your [Source](/docs/sources) URL, including requests with multiple files or repeated field names.

On a [Connection](/docs/connections) using binary-safe multipart handling, Hookdeck delivers the original request bytes, including on retries. You can inspect, search, filter, and transform the form fields without decoding file contents.

> Connections created before October 1, 2026, 18:40 UTC use legacy handling, which treats the body as a UTF-8 string and can alter file bytes. See the [multipart migration guide](/docs/guides/multipart-binary-migration) to move a connection to binary-safe handling.

## Fields and File Metadata

Hookdeck represents a parsed multipart body as an object:

```json
{
  "email": "jane@example.com",
  "tags": ["billing", "urgent"],
  "attachment": {
    "filename": "invoice.pdf",
    "content_type": "application/pdf",
    "size": 48213
  }
}

```

Text fields are strings. Repeated fields become arrays in the order they were sent. Files are described by their filename, content type, and size in bytes; their contents stay in the stored payload.

When a field is repeated, file parts also include a `part_index` identifying their position within that field. Binary parts without a filename have `filename: null`.

## Inspect and Download Files

Open a [request](/docs/requests#inspect-a-request) or [event](/docs/events#inspect-an-event) in the dashboard and expand the Body section. Pretty shows the parsed fields and file metadata, followed by a list of attached files with each file's name, content type, and size.

* Use Download on a file to download its bytes with its filename.
* Enable the preview toggle on an image file to display it inline.
* Select Raw to view the stored multipart body as text, including boundaries and part headers.

## Search Multipart Requests

Text fields are indexed by field name and value, so you can search the body field `email` for `jane@example.com`; its indexed path is `body.email`. File metadata is searchable too, such as `body.attachment.filename`. File contents are not indexed.

## Filter Multipart Requests

On a binary-safe connection, [body filters](/docs/filters) match the parsed fields and file metadata. For example, this body filter matches requests whose `email` field has the specified value:

```json
{
  "email": "jane@example.com"
}

```

Filters on headers, path, and query work as they do for other content types.

## Transform Multipart Requests

On a binary-safe connection, a [transformation](/docs/transformations) receives the parsed object in `request.body`. You can add, edit, or remove text fields:

```js
addHandler('transform', (request, context) => {
  request.body.email = request.body.email.toLowerCase();
  request.body.source = 'hookdeck';
  return request;
});

```

Hookdeck rebuilds the multipart body and keeps the original bytes of retained files. To remove a file, delete its field, or remove its entry from a repeated field's array.

Transformations can't read or edit file contents, rename files, or create new files. Keep each retained file descriptor unchanged, including its `part_index`. If a transformation changes a file descriptor, Hookdeck sends the original file and logs a warning.

To replace the body with JSON, set `request.headers['content-type']` to `application/json` and return a JSON body. This replaces the multipart body, including its files.

### Convert JSON to Multipart

To deliver a JSON object as multipart form fields, set `request.headers['content-type']` to `multipart/form-data`:

```js
addHandler('transform', (request, context) => {
  request.headers['content-type'] = 'multipart/form-data';
  return request;
});

```

Hookdeck generates the boundary and serializes the fields. Strings become text fields, arrays become repeated fields, and other values become JSON text within their field. Objects containing file metadata are also sent as text; they don't create file uploads.

## Unreadable Multipart Bodies

If Hookdeck can't safely parse a multipart body, such as a part without a field name, transformations receive `request.body: null`. You can still change headers, path, and query, and the original body is delivered unchanged. Malformed bodies don't expose fields for search or individual file downloads.