# Send messages via multipart upload

The Multipart Upload flow lets you send messages to Digital Post recipients by uploading files (envelopes + content) directly to the DPP API using standard HTTP `multipart/form-data` requests. Unlike the S3 Delivery flow, where you stage files in your own S3 bucket, this flow handles storage internally: you simply `POST` your files, and DPP takes care of the rest.

## Prerequisites

Before you begin, make sure you have:

- Sender organization: You need an active sender organization with at least one configured sender (`senderId`).
- API credentials: A valid OAuth 2.0 client configured to obtain access tokens from the DPP authorization server.
- Permission: Your API client must have the `SendMessage` permission granted for the sender organization.
- Content files ready: Prepare the documents (`PDF`, `TXT`, `XLSX`, etc.) you want to deliver.


## How It Works

- Prepare your files: Create your content files (`PDF`, `DOCX`, `XLSX`, `TXT`, etc.) and envelope JSON files that define each message's metadata, recipients, body, and attachments.
- Upload via multipart `POST`: Send all files in a single `multipart/form-data` request to `POST /delivery/v1/messages/{externalTransactionId}`.
- DPP processes the delivery: DPP validates the uploaded files, stores them internally, and starts the delivery pipeline.
- Check delivery status: See Step 4 for how to query delivery progress.


## Delivery Lifecycle

```text
Create envelopes + content files -> POST /delivery/v1/messages/{externalTransactionId} -> DPP validates & stores -> DPP processes envelopes
                                                    |
                                                    v
                                          { "transactionId": 0 }
                                     (use externalTransactionId to track)
                                                    |
                                                    v
                         GET /delivery/v1/deliveries/{senderOrganizationId}_{externalTransactionId}
                                                    |
                                                    v
                   Delivery status: Created -> InProgress -> Completed/Failed
                   Message status: Created -> Succeeded/Denied/Failed
```

## Key Concepts

| Concept | Description |
|  --- | --- |
| Envelope | A JSON file with MIME type `application/vnd+e-boks.emf+json` that describes one message: its recipients, body file, attachments, and sender metadata. Each envelope must contain a `messageId` property. |
| Content file | A document (`PDF`, `TXT`, `XLSX`, etc.) referenced by an envelope as body or attachment. The file must use a supported MIME type as defined in the [envelope schema](/apis/schemas/envelope-schema). |
| External Transaction ID | A unique identifier you provide (in the URL path) to represent the message bundle. The external transaction ID is used to internally generate the Delivery ID as `{senderOrganizationId}_{externalTransactionId}` (lowercased and trimmed). The external transaction ID must be unique per organization; reusing an ID returns `409 Conflict`. |


## Validation Rules

- `externalTransactionId` must be unique per organization.
- Each envelope must contain a unique `messageId`.
- Multipart content files must match the envelope `name` and `filename` definitions.
- Content files must use supported MIME types as defined in the [envelope schema](/apis/schemas/envelope-schema).
- All referenced files must exist in the multipart request.
- Envelope files must use the MIME type `application/vnd+e-boks.emf+json`.


## Step 1: Create your envelope JSON

An envelope defines one message to be delivered. It uses the special MIME type `application/vnd+e-boks.emf+json` and must contain a `messageId` property.

We want to send a pay slip to an employee. The message body is a plain-text note informing recipients that their pay slip is attached. The actual pay slip is provided as a PDF attachment: `payslip-may-2026.pdf`.

- Sender: We use `senderId` 3 from organization with ID 6.
- Recipients: Each recipient is uniquely identified by an identity type and value.
- Message body: A plain-text file (`payslip-info.txt`) containing a short message to the recipient.
- Attachment: The pay slip PDF (`payslip-may-2026.pdf`) available for the recipient to download.
- Message ID: We choose `payslip-may-2026-emp-47291`.
- Title: The message subject displayed in the recipient's inbox.


Save the following as `payslip-may-2026-emp-47291.json`:

```json
{
  "messageId": "payslip-may-2026-emp-47291",
  "title": "Your May 2026 payslip",
  "sender": {
    "senderId": 3,
    "organizationId": 6
  },
  "recipients": [
    {
      "identity": {
        "username": "payslip_recipient-1"
      }
    }
  ],
  "body": {
    "name": "payslip-info",
    "title": "Payslip information",
    "mimeType": "text/plain",
    "filename": "payslip-info.txt"
  },
  "attachments": [
    {
      "name": "payslip-may-2026",
      "title": "Payslip May 2026",
      "mimeType": "application/pdf",
      "filename": "payslip-may-2026.pdf"
    }
  ]
}
```

## Step 2: Prepare your content files

Create the content files that your envelope references.

For this example:

`payslip-info.txt` (body - `text/plain`):

```text
Your payslip for May 2026 is attached.
Please review and contact HR with any questions.
```

`payslip-may-2026.pdf` (attachment - `application/pdf`)

## Step 3: Upload via multipart POST

### Multipart file matching rules

The multipart section `name` and `filename` values must match the corresponding `name` and `filename` properties defined in the envelope body and attachments.

Request requires: Valid authentication token with `SendMessage` permission.

```http
POST {{server}}/delivery/v1/messages/bundle-2026-05-payslips?senderOrganizationId=6&name=May 2026 payslips
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
Authorization: Bearer <access_token>
```

Request body (`multipart/form-data`):

```text
------WebKitFormBoundary
Content-Disposition: form-data; name="payslip-info"; filename="payslip-info.txt"
Content-Type: text/plain
Your payslip for May 2026 is attached.
Please review and contact HR with any questions.
------WebKitFormBoundary
Content-Disposition: form-data; name="payslip-may-2026"; filename="payslip-may-2026.pdf"
Content-Type: application/pdf
<binary PDF content>
------WebKitFormBoundary
Content-Disposition: form-data; name="payslip-may-2026-emp-47291"; filename="payslip-may-2026-emp-47291.json"
Content-Type: application/vnd+e-boks.emf+json
{
  "messageId": "payslip-may-2026-emp-47291",
  "title": "Your May 2026 payslip",
  "sender": {
    "senderId": 3,
    "organizationId": 6
  },
  "recipients": [
    { "identity": { "username": "payslip_recipient-1" } }
  ],
  "body": {
    "name": "payslip-info",
    "title": "Payslip information",
    "mimeType": "text/plain",
    "filename": "payslip-info.txt"
  },
  "attachments": [
    {
      "name": "payslip-may-2026",
      "title": "Payslip May 2026",
      "mimeType": "application/pdf",
      "filename": "payslip-may-2026.pdf"
    }
  ]
}
------WebKitFormBoundary--
```

Success response: `200 OK` - The `transactionId` is currently reserved and always returns `0`.

```json
{
  "transactionId": 0
}
```

## Step 4: Check delivery status

Query the status and outcome of your delivery using the `externalTransactionId` provided during the Step 3 multipart upload request.

Request:

Requires: Valid authentication token with `SendMessage` or `ViewSendMessageHistory` permission.

The Delivery ID is constructed as `{senderOrganizationId}_{externalTransactionId}`.

Since we used `senderOrganizationId=6` and `externalTransactionId=bundle-2026-05-payslips` in Step 3, the Delivery ID is `6_bundle-2026-05-payslips`.

```http
GET {{server}}/delivery/v1/deliveries/6_bundle-2026-05-payslips
Authorization: Bearer <access_token>
```

Success response: `200 OK`

```json
{
  "report": {
    "name": "May 2026 payslips",
    "createdDate": "2026-05-25T10:30:00Z",
    "status": "Completed",
    "deliveredEnvelopes": 1,
    "totalEnvelopes": 1,
    "logs": []
  }
}
```

## Recommended Validation Checklist

Before submitting a multipart delivery, verify:

- `externalTransactionId` is unique for the sender organization
- All envelope files exist
- Each envelope has a unique `messageId`
- Envelope files use content type `application/vnd+e-boks.emf+json`
- All referenced files exist in the multipart request
- Multipart part `name` and `filename` match envelope `body` and `attachments` references
- The caller has `SendMessage` permission for the sender organization


Completing this checklist reduces delivery failures.

## What Happens After Submission

When a multipart delivery request is submitted, the platform:

1. Receives envelope and content files from the multipart request and stores them internally.
2. Validates envelope structure and metadata.
3. Verifies that all referenced files are present in the uploaded multipart payload.
4. Scans content files.
5. Resolves recipient mailboxes.
6. Applies sender and feature rules.
7. Publishes messages atomically at envelope level (all recipients receive the message, or none do).


## Next Steps

After submitting the multipart request, continue with:

- [Verify and Troubleshoot](/getting-started/verify-delivery)