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

# Upload Project Document

> Upload a guideline, glossary, or character list to a single project as a file, without hosting it yourself

Attaches a project document by sending the file itself as `multipart/form-data`. Use this when you have the file locally and do not want to host it or generate a pre-signed URL first.

This is the same operation as [Attach Project Document](/apis/ollang-api-reference/attach-project-document); only the way you supply the file differs. The document applies to this project only, together with the guidelines of the project's folder.

> [!NOTE]
>
> Send the file in a form field named `file`. The file must be smaller than
> 50 MiB (52,428,800 bytes). Files at or above this limit return `413`.

```bash cURL theme={null}
curl -X POST "https://api-integration.ollang.com/integration/project/60b8d6f1e1b9b1d8c6c0d8e3/docs/upload" \
  -H "X-Api-Key: $OLLANG_API_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/episode-5-slang-notes.pdf" \
  -F "type=guideline" \
  -F "name=Episode 5 slang notes" \
  -F "language=en"
```

```javascript JavaScript theme={null}
const projectId = "60b8d6f1e1b9b1d8c6c0d8e3";

const formData = new FormData();
formData.append("file", guidelineFile);
formData.append("type", "guideline");
formData.append("name", "Episode 5 slang notes");
formData.append("language", "en");

const response = await fetch(
  `https://api-integration.ollang.com/integration/project/${projectId}/docs/upload`,
  {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.OLLANG_API_KEY,
    },
    body: formData,
  },
);

const doc = await response.json();
console.log("Attached document:", doc.id);
```

```python Python theme={null}
import os
import requests

project_id = "60b8d6f1e1b9b1d8c6c0d8e3"

files = {'file': open('episode-5-slang-notes.pdf', 'rb')}
data = {
    'type': 'guideline',
    'name': 'Episode 5 slang notes',
    'language': 'en',
}
headers = {'X-Api-Key': os.environ['OLLANG_API_KEY']}

response = requests.post(
    f'https://api-integration.ollang.com/integration/project/{project_id}/docs/upload',
    files=files,
    data=data,
    headers=headers,
)

doc = response.json()
print("Attached document:", doc["id"])
```

```php PHP theme={null}
$projectId = '60b8d6f1e1b9b1d8c6c0d8e3';

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://api-integration.ollang.com/integration/project/{$projectId}/docs/upload",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => array(
        'file' => new CURLFile('/path/to/episode-5-slang-notes.pdf'),
        'type' => 'guideline',
        'name' => 'Episode 5 slang notes',
        'language' => 'en',
    ),
    CURLOPT_HTTPHEADER => array(
        'X-Api-Key: ' . getenv('OLLANG_API_KEY')
    ),
));

$response = curl_exec($curl);
$doc = json_decode($response, true);
curl_close($curl);

echo "Attached document: " . $doc['id'];
```

```go Go theme={null}
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    projectID := "60b8d6f1e1b9b1d8c6c0d8e3"
    url := "https://api-integration.ollang.com/integration/project/" + projectID + "/docs/upload"

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    file, _ := os.Open("episode-5-slang-notes.pdf")
    defer file.Close()

    part, _ := writer.CreateFormFile("file", "episode-5-slang-notes.pdf")
    io.Copy(part, file)

    writer.WriteField("type", "guideline")
    writer.WriteField("name", "Episode 5 slang notes")
    writer.WriteField("language", "en")
    writer.Close()

    req, _ := http.NewRequest("POST", url, body)
    req.Header.Set("X-Api-Key", os.Getenv("OLLANG_API_KEY"))
    req.Header.Set("Content-Type", writer.FormDataContentType())

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    respBody, _ := io.ReadAll(resp.Body)

    var doc map[string]interface{}
    json.Unmarshal(respBody, &doc)

    fmt.Println("Attached document:", doc["id"])
}
```

```java Java theme={null}
String projectId = "60b8d6f1e1b9b1d8c6c0d8e3";

HttpResponse<String> response = Unirest
  .post("https://api-integration.ollang.com/integration/project/" + projectId + "/docs/upload")
  .header("X-Api-Key", System.getenv("OLLANG_API_KEY"))
  .field("file", new File("episode-5-slang-notes.pdf"))
  .field("type", "guideline")
  .field("name", "Episode 5 slang notes")
  .field("language", "en")
  .asString();

JSONObject doc = new JSONObject(response.getBody());
System.out.println("Attached document: " + doc.getString("id"));
```

## Authorizations

This endpoint requires API key authentication. Include your API key in the request header:

* **Header name**: `X-Api-Key`
* **Header value**: Your API key from the Ollang dashboard
* **Format**: `X-Api-Key: your-api-key-here`

The examples read the key from the `OLLANG_API_KEY` environment variable; set it before running them.

The project must belong to the API key's account; other projects return `404`.

The API key user also needs write access, the same as for folder documents: the
account owner, team-manager or order-creator role, or project manager of the
project's folder. Other keys, such as view-only users, receive a `403`.

## Path Parameters

**projectId** `string` *required*

The unique identifier of the project to attach the document to. Retrieve
project IDs with [Retrieve All
Projects](/apis/ollang-api-reference/retrieve-all-projects).

## Body Parameters

Send the request as `multipart/form-data`.

**file** `file` *required*

The document to upload, smaller than 50 MiB (52,428,800 bytes).

**type** `string` *required*

The kind of project document. One of:

* `guideline` — style and tone guidance
* `guideline_glossary` — terminology list
* `character_list` — character names and notes

**name** `string`

Display name of the document. Defaults to the uploaded file's own name. The
file's extension is appended when the name does not already end with it.

**language** `string`

BCP-47 language tag of the document (e.g. `en`). Defaults to the project's
source language.

## Response

Returns the created project document, identical to [Attach Project
Document](/apis/ollang-api-reference/attach-project-document).

**id** `string`

Unique identifier of the project document. Pass this to [Update Project
Document](/apis/ollang-api-reference/update-project-document) or [Remove
Project Document](/apis/ollang-api-reference/delete-project-document).

**name** `string`

Display name of the document.

**type** `string`

One of `guideline`, `guideline_glossary`, or `character_list`.

**url** `string`

A pre-signed download link for the stored copy Ollang created, valid for 12
hours.

**size** `number`

Size of the stored document in bytes.

**sourceLanguage** `string`

The `language` supplied with the request, or the project's source language.

**projectId** `string`

Identifier of the project the document is attached to.

**createdAt** `string`

When the document was attached, in ISO 8601 format.

```json 201 theme={null}
{
  "id": "60b8d6f1e1b9b1d8c6c0d8f5",
  "name": "Episode 5 slang notes.pdf",
  "type": "guideline",
  "url": "https://ollang-docs.s3.eu-central-1.amazonaws.com/60b8d6f1e1b9b1d8c6c0d8e5/episode-5-slang-notes.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=...",
  "size": 90211,
  "sourceLanguage": "en",
  "projectId": "60b8d6f1e1b9b1d8c6c0d8e3",
  "parentDocId": null,
  "clientId": "60b8d6f1e1b9b1d8c6c0d8e5",
  "createdAt": "2026-10-21T08:02:51.104Z",
  "updatedAt": "2026-10-21T08:02:51.104Z"
}
```

```json 413 theme={null}
{
  "code": -1,
  "error": "UnknownError",
  "message": "unknown error",
  "detail": "File too large"
}
```

```json 401 theme={null}
{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "code": "UNAUTHORIZED"
}
```

```json 403 theme={null}
{
  "statusCode": 403,
  "message": "You don't have permission to perform this action. Please contact your account admin.",
  "error": "Forbidden"
}
```

```json 404 theme={null}
{
  "statusCode": 404,
  "message": "Project not found",
  "error": "Not Found"
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.