# Merge two password protected documents in a specified order

Using [🤖/document/merge](/docs/robots/document-merge.md), you can merge several pdf documents together in a single file.

There's no need to worry if you're handling password protected documents either, as you can simply specify an array of passwords to the `input_passwords` parameter, which will be used for each document.

To specify an order for the documents, use the "as" syntax, as shown in the demo below.

Step 1

### Filter files

We let you reject, or direct files against different encoding Steps. [Learn more ›](/services/file-filtering.md)

![first\_document.pdf](https://tl-preview.tlcdn.com/demo-preview/bf/c26632059a4776a139f970fb4deee8/first_document.pdf?w=214\&h=300\&cb=11)

[first\_document.pdf](https://demos.transloadit.com/bf/c26632059a4776a139f970fb4deee8/first%5Fdocument.pdf)

application/pdf · 14 KB

```
"first": {
  "use": ":original",
  "robot": "/file/filter",
  "result": true,
  "accepts": [
    [
      "${file.basename}",
      "==",
      "first_document"
    ]
  ]
}
```

🤖 [/file/filter](/docs/robots/file-filter.md)

This bot directs files to different encoding Steps based on your conditions

Step 2

### Filter files

We let you reject, or direct files against different encoding Steps. [Learn more ›](/services/file-filtering.md)

![second\_document.pdf](https://tl-preview.tlcdn.com/demo-preview/92/776953002a4224a349c9bcf3f3467b/second_document.pdf?w=214\&h=300\&cb=11)

[second\_document.pdf](https://demos.transloadit.com/92/776953002a4224a349c9bcf3f3467b/second%5Fdocument.pdf)

application/pdf · 14 KB

```
"second": {
  "use": ":original",
  "robot": "/file/filter",
  "result": true,
  "accepts": [
    [
      "${file.basename}",
      "==",
      "second_document"
    ]
  ]
}
```

🤖 [/file/filter](/docs/robots/file-filter.md)

This bot directs files to different encoding Steps based on your conditions

Step 3

### Merge documents into one

We can process your documents in an automated way, saving you costly resources. [Learn more ›](/services/document-processing.md)

![first\_document.pdf](https://tl-preview.tlcdn.com/demo-preview/5a/e2a076b8f54b4a8ff09f0b63ef38e9/first_document.pdf?w=214\&h=300\&cb=11)

[first\_document.pdf](https://demos.transloadit.com/5a/e2a076b8f54b4a8ff09f0b63ef38e9/first%5Fdocument.pdf)

application/pdf · 25 KB · 1238 × 1752

```
"merge": {
  "use": [
    {
      "name": "first",
      "as": "document_1"
    },
    {
      "name": "second",
      "as": "document_2"
    }
  ],
  "robot": "/document/merge",
  "result": true,
  "input_passwords": [
    "password1",
    "password2"
  ]
}
```

🤖 [/document/merge](/docs/robots/document-merge.md)

This bot concatenates several PDF documents into a single file

Step 4

### Export files to Amazon S3

We export to the storage platform of your choice. [Learn more ›](/services/file-exporting.md)

`first`

* [https://demos.transloadit.com/bf/c26632059a4776a139f970fb4deee8/first\_document.pdf⁠](https://demos.transloadit.com/bf/c26632059a4776a139f970fb4deee8/first%5Fdocument.pdf)

`second`

* [https://demos.transloadit.com/92/776953002a4224a349c9bcf3f3467b/second\_document.pdf⁠](https://demos.transloadit.com/92/776953002a4224a349c9bcf3f3467b/second%5Fdocument.pdf)

`merge`

* [https://demos.transloadit.com/5a/e2a076b8f54b4a8ff09f0b63ef38e9/first\_document.pdf⁠](https://demos.transloadit.com/5a/e2a076b8f54b4a8ff09f0b63ef38e9/first%5Fdocument.pdf)

```
"exported": {
  "use": [
    "first",
    "second",
    "merge",
    ":original"
  ],
  "robot": "/s3/store",
  "credentials": "demo_s3_credentials",
  "url_prefix": "https://demos.transloadit.com/"
}
```

🤖 [/s3/store](/docs/robots/s3-store.md)

This bot exports encoding results to Amazon S3

## Live Demo. See for yourself

Loading Uppy demo…

## Build this in your own language

```
<!-- This pulls Uppy from our CDN -->
<!-- For smaller self-hosted bundles, install Uppy and plugins manually: -->
<!-- npm i --save @uppy/core @uppy/dashboard @uppy/remote-sources @uppy/transloadit ... -->
<link
  href="https://releases.transloadit.com/uppy/v3.10.0/uppy.min.css"
  rel="stylesheet"
/>
<button id="browse">Select Files</button>
<script type="module">
  import {
    Uppy,
    Dashboard,
    ImageEditor,
    RemoteSources,
    Transloadit,
  } from 'https://releases.transloadit.com/uppy/v3.10.0/uppy.min.mjs'
  const uppy = new Uppy()
    .use(Transloadit, {
      waitForEncoding: true,
      alwaysRunAssembly: true,
      assemblyOptions: {
        params: {
          // It's often better store encoding instructions in your account
          // and use a `template_id` instead of adding these steps inline
          steps: {
            first: {
              use: ':original',
              robot: '/file/filter',
              result: true,
              accepts: [['${file.basename}', '==', 'first_document']],
            },
            second: {
              use: ':original',
              robot: '/file/filter',
              result: true,
              accepts: [['${file.basename}', '==', 'second_document']],
            },
            merge: {
              use: [
                {
                  name: 'first',
                  as: 'document_1',
                },
                {
                  name: 'second',
                  as: 'document_2',
                },
              ],
              robot: '/document/merge',
              result: true,
              input_passwords: ['password1', 'password2'],
            },
            exported: {
              use: ['first', 'second', 'merge', ':original'],
              robot: '/s3/store',
              credentials: 'demo_s3_credentials',
              url_prefix: 'https://demos.transloadit.com/',
            },
          },
        },
      },
    })
    .use(Dashboard, { trigger: '#browse' })
    .use(ImageEditor, { target: Dashboard })
    .use(RemoteSources, {
      companionUrl: 'https://api2.transloadit.com/companion',
    })
    .on('complete', ({ transloadit }) => {
      // Due to `waitForEncoding:true` this is fired after encoding is done.
      // Alternatively, set `waitForEncoding` to `false` and provide a `notify_url`
      console.log(transloadit) // Array of Assembly Statuses
      for (const assembly of transloadit) {
        console.log(assembly.results) // Array of all encoding results
      }
    })
    .on('error', (error) => {
      console.error(error)
    })
</script>

```

[Read docs: Browsers](/docs/sdks/uppy.md)

## So many ways to integrate

Transloadit is a service for companies with developers. And there are many ways developers can put Transloadit to good use inside your company to automate media processing.

#### Bulk imports

Add one of our [import Robots](/services/file-importing.md) to acquire and transcode massive media libraries.

#### Handling uploads

We are *the* experts at reliably [handling uploads](/services/handling-uploads.md). We wrote the [protocol⁠](https://tus.io/) for it.

#### Front-end integration

We integrate with web browsers via our next-gen file uploader [Uppy⁠](https://uppy.io/docs/guides/uppy-transloadit/) and SDKs for Android and iOS.

#### Back-end integration

Send us batch jobs in any server language using one of our [SDKs](/docs/sdks.md) or directly interfacing with our [REST API](/docs/api.md).

#### Pingbacks

Configure a [notify\_url](/services/content-delivery.md) to let your server receive transcoding results JSON in the `transloadit` POST field.

#### On-demand

Use our [Smart CDN](/services/file-importing.md) to adapt files on-demand and stream them directly to your users.

[Browsers](/docs/sdks/uppy.md)[TransloaditKit](/docs/sdks/transloaditkit.md)[Ruby SDK](/docs/sdks/ruby-sdk.md)[HTTP REST API](/docs/api.md)[Python SDK](/docs/sdks/python-sdk.md)[PHP SDK](/docs/sdks/php-sdk.md)[Node.js SDK](/docs/sdks/node-sdk.md)[Java SDK](/docs/sdks/java-sdk.md)[Go SDK](/docs/sdks/go-sdk.md)[cURL](/docs/sdks/curl.md)[Convex](/docs/sdks/convex.md)

[Browsers](/docs/sdks/uppy.md)[TransloaditKit](/docs/sdks/transloaditkit.md)[Ruby SDK](/docs/sdks/ruby-sdk.md)[HTTP REST API](/docs/api.md)[Python SDK](/docs/sdks/python-sdk.md)[PHP SDK](/docs/sdks/php-sdk.md)[Node.js SDK](/docs/sdks/node-sdk.md)[Java SDK](/docs/sdks/java-sdk.md)[Go SDK](/docs/sdks/go-sdk.md)[cURL](/docs/sdks/curl.md)[Convex](/docs/sdks/convex.md)

[Browsers](/docs/sdks/uppy.md)[TransloaditKit](/docs/sdks/transloaditkit.md)[Ruby SDK](/docs/sdks/ruby-sdk.md)[HTTP REST API](/docs/api.md)[Python SDK](/docs/sdks/python-sdk.md)[PHP SDK](/docs/sdks/php-sdk.md)[Node.js SDK](/docs/sdks/node-sdk.md)[Java SDK](/docs/sdks/java-sdk.md)[Go SDK](/docs/sdks/go-sdk.md)[cURL](/docs/sdks/curl.md)[Convex](/docs/sdks/convex.md)

## Other cool demos

* [View demo→Document ProcessingAdd a header or footer to a PDF](/demos/document-processing/add-header-or-footer-to-pdf.md)
* [View demo→Document ProcessingConvert all pages of a document into an animated GIF](/demos/document-processing/convert-all-pages-of-a-document-into-an-animated-gif.md)
* [View demo→Image ProcessingAdd a sepia effect to an image](/demos/image-processing/add-sepia-effect-to-an-image.md)

Try Transloadit

## Ready to get started?

Join thousands of developers who trust Transloadit for their file processing needs.

Building file processing from scratch

Ready-to-use API & SDKs

Scaling infrastructure headaches

Auto-scaling global infrastructure

Managing codec updates

Always up-to-date processing

Handling file security

Enterprise-grade security

Supporting all file formats

1000+ formats & codecs supported

Fragmented media tooling

One API for file workflows

GDPR

GDPR

HIPAA

HIPAA

ISO 27001ISO27001

ISO 27001

AES-256

AES-256

SOC 2 Type II

SOC 2 Type II

[Try Transloadit for Free](/c/signup/)

[Try Transloadit for Free](/c/signup/)

No credit card needed · Cancel anytime
