> ## 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.

# Attach Project Document

> Attach a guideline, glossary, or character list to a single project

Attaches a document to one project only. Use it when a single project needs guidance that the rest of its folder should not get. To give every project in a folder the same document, use [Attach Folder Document](/apis/ollang-api-reference/attach-folder-document) instead.

This is the API equivalent of uploading a guideline in a project's **Guidelines** panel in the dashboard. The document is used for that project's orders together with the guidelines of the project's folder. See [Memory, Guidelines, and Custom Instructions](/memory-guidelines-custom-instructions) for how the levels relate.

> [!NOTE]
>
> Ollang fetches the document from the URL you supply and stores its own copy,
> so a short-lived pre-signed URL is fine. The URL only needs to be readable at
> the moment of the call, and the document stays available to later orders after
> the signature expires.

> [!TIP]
>
> Have the file locally rather than hosted? Use [Upload Project
> Document](/apis/ollang-api-reference/upload-project-document) to send it
> directly as `multipart/form-data`, with no URL needed.

```bash cURL theme={null}
curl -X POST "https://api-integration.ollang.com/integration/project/60b8d6f1e1b9b1d8c6c0d8e3/docs" \
  -H "X-Api-Key: $OLLANG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...",
    "type": "guideline",
    "name": "Episode 5 slang notes",
    "language": "en"
  }'
```

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

const response = await fetch(
  `https://api-integration.ollang.com/integration/project/${projectId}/docs`,
  {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.OLLANG_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      url: "https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...",
      type: "guideline",
      name: "Episode 5 slang notes",
      language: "en",
    }),
  },
);

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

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

project_id = "60b8d6f1e1b9b1d8c6c0d8e3"

response = requests.post(
    f"https://api-integration.ollang.com/integration/project/{project_id}/docs",
    headers={
        "X-Api-Key": os.environ["OLLANG_API_KEY"],
        "Content-Type": "application/json",
    },
    json={
        "url": "https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...",
        "type": "guideline",
        "name": "Episode 5 slang notes",
        "language": "en",
    },
)

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

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

$payload = json_encode([
    'url' => 'https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...',
    'type' => 'guideline',
    'name' => 'Episode 5 slang notes',
    'language' => 'en',
]);

$curl = curl_init();

curl_setopt_array($curl, array(
    CURLOPT_URL => "https://api-integration.ollang.com/integration/project/{$projectId}/docs",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_HTTPHEADER => array(
        'X-Api-Key: ' . getenv('OLLANG_API_KEY'),
        'Content-Type: application/json'
    ),
));

$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"
    "net/http"
    "os"
)

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

    payload, _ := json.Marshal(map[string]interface{}{
        "url":      "https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...",
        "type":     "guideline",
        "name":     "Episode 5 slang notes",
        "language": "en",
    })

    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
    req.Header.Set("X-Api-Key", os.Getenv("OLLANG_API_KEY"))
    req.Header.Set("Content-Type", "application/json")

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

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

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

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

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

JSONObject payload = new JSONObject()
  .put("url", "https://your-bucket.s3.amazonaws.com/episode-5-slang-notes.pdf?X-Amz-Signature=...")
  .put("type", "guideline")
  .put("name", "Episode 5 slang notes")
  .put("language", "en");

HttpResponse<String> response = Unirest
  .post("https://api-integration.ollang.com/integration/project/" + projectId + "/docs")
  .header("X-Api-Key", System.getenv("OLLANG_API_KEY"))
  .header("Content-Type", "application/json")
  .body(payload.toString())
  .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

**url** `string` *required*

A URL Ollang can read the document from, such as a pre-signed S3 URL. Must be
`http` or `https`, must resolve to a public address, and must return the file
without a redirect. The document must be 50 MB or smaller.

**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 file name in the URL. The
file's extension is appended when the name does not already end with it, so
`Episode 5 slang notes` is stored as `Episode 5 slang notes.pdf`.

**size** `number`

Size of the document in bytes. Ollang records the size of the file it actually
fetched, so this value is informational.

**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.

**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.

**parentDocId** `string`

Always `null` for a document attached to the project directly.

**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 400 theme={null}
{
  "statusCode": 400,
  "message": "Could not fetch the document from the provided URL. Make sure it is publicly readable and under 50 MB.",
  "error": "Bad Request"
}
```

```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.