> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.emtelligent.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.emtelligent.com/_mcp/server.

# Upload a document and process it

POST https://<your-prep-endpoint>/emtellisplit/v{api_version}/submit-upload
Content-Type: multipart/form-data

The file names, not the contents, must have the extensions listed for each part.

API version 1 stores each file under its own file name, and the output keys contain the stem
of the document's file name. API version 2 stores each file as the part name plus the suffix
of the file name, and the output keys do not contain file names.

Reference: https://docs.emtelligent.com/prep/api/v-1-submit-upload

## Authentication

- `Authorization` header (bearer token, required) — Your API key

## Request

### Path parameters

- `api_version` (enum, required)
  - Allowed values: `1`, `2`

### Body (multipart/form-data)

This endpoint expects a multipart form with multiple files.

- `document` (file, required) — The document. The file name must end with .PDF, .pdf, .tif, .TIF
- `splits_json` (file, optional) — The split metadata. The file name must end with json
- `best_ocr` (file, optional) — The OCR text. The file name must end with txt
- `operation` (enum, optional)
- `params` (string, optional) — A JSON object of SubmitParams

## Response

### 200

OK

- `job_id` (string, required)

## Errors

### 400 Bad Request Error

Invalid request, or direct upload is not enabled on this server

- `error` (string, required)

### 401 Unauthorized Error

Missing or invalid credentials

- `error` (string, required)

### 402 Payment Required Error

Organization suspended, or not enough credit

- `V1_submit_uploadRequestPaymentRequiredError`
  - InsufficientCreditResponse: InsufficientCreditResponse
  - ErrorResponse: ErrorResponse

### 413 Content Too Large Error

The request is larger than the server's upload limit

- `error` (string, required)

### 500 Internal Server Error

Server error, or the server is in maintenance mode

- `error` (string, required)

### 503 Service Unavailable Error

Service temporarily unavailable

- `error` (string, required)

## Types

### InsufficientCreditResponse

- `error` (string, required)
- `available_cents` (integer, required)
- `requested_cents` (integer, required)

### ErrorResponse

- `error` (string, required)

## Examples

**Request**

```json
{
  "best_ocr": "<file: <file1>>",
  "document": "<file: string>",
  "splits_json": "<file: <file1>>"
}
```

**Response**

```json
{
  "job_id": "string"
}
```

**SDK Code**

```python
import requests

url = "https://api.example.com/emtellisplit/v1/submit-upload"

files = {
    "best_ocr": "open('<file1>', 'rb')",
    "document": "open('string', 'rb')",
    "splits_json": "open('<file1>', 'rb')"
}
payload = {
    "operation": ,
    "params": 
}
headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, data=payload, files=files, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.example.com/emtellisplit/v1/submit-upload';
const form = new FormData();
form.append('best_ocr', '<file1>');
form.append('document', 'string');
form.append('operation', '');
form.append('params', '');
form.append('splits_json', '<file1>');

const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.example.com/emtellisplit/v1/submit-upload"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"best_ocr\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"operation\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"params\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"splits_json\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.example.com/emtellisplit/v1/submit-upload")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"best_ocr\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"operation\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"params\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"splits_json\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.example.com/emtellisplit/v1/submit-upload")
  .header("Authorization", "Bearer <token>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"best_ocr\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"operation\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"params\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"splits_json\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.example.com/emtellisplit/v1/submit-upload', [
  'multipart' => [
    [
        'name' => 'best_ocr',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'document',
        'filename' => 'string',
        'contents' => null
    ],
    [
        'name' => 'splits_json',
        'filename' => '<file1>',
        'contents' => null
    ]
  ]
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.example.com/emtellisplit/v1/submit-upload");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"best_ocr\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"document\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"operation\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"params\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"splits_json\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]
let parameters = [
  [
    "name": "best_ocr",
    "fileName": "<file1>"
  ],
  [
    "name": "document",
    "fileName": "string"
  ],
  [
    "name": "operation",
    "value": 
  ],
  [
    "name": "params",
    "value": 
  ],
  [
    "name": "splits_json",
    "fileName": "<file1>"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.example.com/emtellisplit/v1/submit-upload")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```