> ## Documentation Index
> Fetch the complete documentation index at: https://help.draftable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Submitting files: direct upload or source URL

> The two ways to give Draftable your documents, when to use each, and why pre-signed storage URLs are usually the best option for files already in S3 or Azure.

There are two ways to give Draftable the documents you want compared, and the choice has real consequences for performance, reliability and how much data moves through your own servers.

| Method                                                  | You send                         | Draftable does            |
| :------------------------------------------------------ | :------------------------------- | :------------------------ |
| **Direct upload** (`left.file` / `right.file`)          | The file's bytes, in the request | Uses them immediately     |
| **Source URL** (`left.source_url` / `right.source_url`) | A URL                            | Downloads the file itself |

<Warning>
  For each side, supply **exactly one** of the two. Sending both `file` and `source_url` for the same side is rejected as a malformed request, as is sending neither.
</Warning>

You can mix methods across sides. Uploading the left file while giving a URL for the right is perfectly valid.

## Method 1: direct upload

Send the file's bytes as part of a `multipart/form-data` request. Use this when the document is on your server, was just uploaded by a user, or is generated on the fly and does not exist at any URL.

```bash theme={null}
curl "https://api.draftable.com/v1/comparisons" \
     -H "Authorization: Token {auth_token}" \
     -F "left.file_type=pdf"  -F "left.file=@path/to/left.pdf" \
     -F "right.file_type=pdf" -F "right.file=@path/to/right.pdf"
```

The client libraries accept a file path or an open file object, so you can stream a file without loading it into memory:

```python theme={null}
comparison = client.comparisons.create(
    left=draftable.make_side("path/to/left.pdf", file_type="pdf"),
    right=draftable.make_side("path/to/right.pdf", file_type="pdf"),
)
```

**Upside:** it always works. There is nothing for Draftable to reach, so firewalls, private networks and authentication are irrelevant.

**Downside:** the bytes travel twice, once from wherever they live to your server, then from your server to Draftable. For large files that is time and bandwidth you may not need to spend.

<Tip>
  Because a large upload takes time, this is a good case for creating comparisons in a background job. Choose your own identifier, hand the user a viewer URL with `wait` immediately, and let the upload finish behind the scenes.
</Tip>

## Method 2: source URL

Give Draftable a URL and it downloads the file directly.

```bash theme={null}
curl "https://api.draftable.com/v1/comparisons" \
     -H "Authorization: Token {auth_token}" \
     -F "left.file_type=pdf"  -F "left.source_url=https://example.com/left.pdf" \
     -F "right.file_type=pdf" -F "right.source_url=https://example.com/right.pdf"
```

### Requirements

The URL must be reachable **by Draftable, from the public internet, without authentication**.

<Warning>
  A URL that works in your browser is not necessarily reachable by Draftable. Anything on an internal network, behind a VPN, requiring a login, or returning an HTML page instead of the file itself will fail. If your documents are not publicly reachable, upload them directly instead.
</Warning>

### What happens if the download fails

Draftable attempts the download **up to four times**. If every attempt fails, the comparison is marked as `failed`, and the `error_message` describes the download attempts.

This is worth knowing when debugging: a comparison that accepted cleanly and failed later is very often a `source_url` that Draftable could not reach. See [Handling errors and comparison failures](/hc/en-us/articles/Draftable-API-handling-errors).

## The best of both: pre-signed storage URLs

If your documents already live in cloud storage such as **Amazon S3** or **Azure Blob Storage**, there is a better option than either of the above.

Generate a **pre-signed, single-use URL** and pass that as the `source_url`. Draftable downloads the file straight from your storage provider.

<Note>
  This avoids moving the data through your own servers entirely. Your application never downloads the file just to upload it again, which saves bandwidth, reduces latency, and removes your server as a bottleneck for large documents.
</Note>

It also keeps your storage private. The URL grants time-limited access to one object, so the bucket itself stays closed.

```python theme={null}
url = s3.generate_presigned_url(
    "get_object",
    Params={"Bucket": "my-documents", "Key": "contracts/left.pdf"},
    ExpiresIn=900,
)
```

<Warning>
  Give the pre-signed URL a long enough expiry to survive the download, including retries. A URL that expires seconds after you create it can fail before Draftable has fetched the file. A window of several minutes is a reasonable starting point.
</Warning>

## Which should you use?

| Situation                                              | Use                       |
| :----------------------------------------------------- | :------------------------ |
| Files in S3, Azure Blob or similar                     | **Pre-signed source URL** |
| Files already public on the web                        | **Source URL**            |
| Files on your own server or freshly uploaded by a user | **Direct upload**         |
| Files on an internal network, behind auth, or on a VPN | **Direct upload**         |
| Files generated in memory                              | **Direct upload**         |

## Do not forget the file type

Whichever method you use, `left.file_type` and `right.file_type` are **required**. Draftable does not infer the type from the file name, the URL, or the content.

Declaring the wrong type is a common cause of failure, and the error often surfaces only in the viewer's JavaScript console. Accepted values are `pdf`, `doc`, `docx`, `docm`, `ppt`, `pptx`, `pptm`, `rtf` and `txt`.

## Related articles

<CardGroup>
  <Card title="Creating a comparison" icon="file-import" href="/hc/en-us/articles/Draftable-API-creating-a-comparison" iconType="solid" horizontal />

  <Card title="Comparison speeds and batch processing" icon="gauge-high" href="/hc/en-us/articles/Draftable-API-comparison-speeds" iconType="solid" horizontal />

  <Card title="Handling errors and failures" icon="triangle-exclamation" href="/hc/en-us/articles/Draftable-API-handling-errors" iconType="solid" horizontal />
</CardGroup>
