# Send documents

You may need to attach documents to certain Dashdoc resources, such as:

* Transport orders (e.g. weight notes, transport documents)
* Invoices (e.g. proof of delivery)
* Site entities (e.g. security protocols, instructions)

To support this, the Dashdoc API allows file uploads using **`multipart/form-data`** requests.

***

### Requirements

When uploading documents, make sure to:

* Use the HTTP header:

  ```http
  Content-Type: multipart/form-data
  ```
* Let your HTTP client **automatically generate the `boundary`** parameter, which is required by the multipart encoding.

Example of the generated header:

```http
Content-Type: multipart/form-data; boundary=Boundary_42_15460972_1713531308867
```

{% hint style="warning" %}
The `boundary` is a unique string used to separate parts in the request body. It **must match** what's used in the actual body content.
{% endhint %}

***

### Examples

**Example: Using `curl`**

```bash
curl -X POST https://www.dashdoc.com/api/v4/documents/ \
  -H "Authorization: Token your_api_token" \
  -F "file=@weight_note.pdf" \
  -F "type=Documents" \
  -F "transport=1f527452-45f4-11eb-a722-0242ac140004"

```

{% hint style="success" %}
`-F` automatically handles the `Content-Type` and boundary.
{% endhint %}

***

**Example: Using Python (`requests`)**

```python
import requests

url = "https://www.dashdoc.com/api/v4/transport-messages/"
headers = {
    "Authorization": "Token your_api_token"
}
files = {
    "file": ("weight_note.pdf", open("weight_note.pdf", "rb")),
}
data = {
    "type": "documents",
    "transport": "1f527452-45f4-11eb-a722-0242ac140004"
}

response = requests.post(url, headers=headers, files=files, data=data)
print(response.status_code, response.json())
```

#### **Example: Using Postman**

In Postman, when you select **"form-data"** as the body type and add your file and fields, Postman will automatically set the correct `Content-Type: multipart/form-data` header. It also handles the `boundary` parameter internally — this value is generated dynamically when the request is sent and does not need to be set manually.

<figure><img src="https://3074350244-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LU-jgnMbbOKXxePIFGq%2Fuploads%2Fgit-blob-3d53f9f6b2e0efd8b7333bdb7ce442759a4e93a6%2Fimage%20(14).png?alt=media" alt=""><figcaption></figcaption></figure>

***

### Common Errors & Troubleshooting

**Error:**

<pre class="language-json"><code class="lang-json"><strong>{"detail":"Multipart form parse error - Invalid boundary in multipart: None"}
</strong></code></pre>

**Cause**: The boundary is missing from the `Content-Type` header or does not match the request body.

**Fix**:

* Don't set the `Content-Type` header manually. Let your HTTP client or library handle it.
* If you're generating the request manually, make sure:
  * A unique boundary is defined.
  * It appears both in the `Content-Type` header and correctly wraps parts in the body.

#### **Error: `400 Bad Request`**

**Cause**:

* Required fields like `type` or `transport` are missing.
* The file is missing or empty.
* Invalid values (e.g., unsupported type).

**Fix**:

* Double-check field names and values.
* Ensure the `type` field is one of the expected values (`"note"`,`"load_verification"`,`"share"`,`"document"`or`"photo"`).
* Ensure `transport` is a valid transport UID from your Dashdoc environment.

***

### Best Practices

* Test your request using Postman to inspect headers and payloads.
* Let your HTTP client manage the `Content-Type` and boundary.
* Validate required fields early in your application to avoid request failures.
