> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/maiagent-tech-ja/api-integration/api_knowledge.md).

# Presigned ファイルアップロードモード

現在 MaiAgent でファイルのアップロードが必要となる箇所は 2 か所あります。

1. ナレッジベースへのドキュメントアップロード
2. メッセージで使用する添付ファイルのアップロード

## Presigned アップロードモード

MaiAgent は **Presigned アップロードモード**に対応しています。このモードでは、クライアント側がサーバーを経由せずに、ファイルを直接クラウドストレージ（S3 など）へアップロードできます。このモードを使用する場合、サーバーは有効期限とセキュリティを備えた Presigned URL の生成のみを担当し、クライアントはその URL を利用して直接ファイルをアップロードします。

#### 従来のアップロードモードとの違い：

1. **データの流れ**
   * 従来モード：ファイルはサーバーを経由し、サーバーがクラウドストレージへアップロードします。
   * Presigned モード：ファイルはクライアントから直接クラウドへアップロードされ、サーバーがファイルを処理する負担を回避できます。
2. **パフォーマンスとコスト**
   * 従来モードはサーバーリソースの消費が過大になり、データ転送コストが増加する可能性があります。
   * Presigned モードはサーバー負荷を軽減し、パフォーマンスを向上させ、転送コストを削減します。
3. **セキュリティ**
   * Presigned URL には署名と有効期限が含まれており、アップロードリクエストが認可されたユーザーによって指定された時間内にのみ使用されることを保証します。

このモードは、特に大容量ファイルや高頻度のアップロードのシーンに適しており、効率を高めると同時に高いセキュリティを維持できます。

#### 事前署名アップロードのフロー図

```mermaid
sequenceDiagram
    participant Client as Client
    participant Server as Sever
    participant S3 as Storage(S3)

    Note over Client,S3: 事前署名アップロードフロー
    
    Client->>+Server: 1. 事前署名 URL をリクエスト
    Note right of Client: POST /api/v1/upload-presigned-url/<br/>ファイル名・タイプ・サイズを含む
    
    Server->>Server: 2. リクエストパラメータを検証
    Server->>Server: 3. 事前署名パラメータを生成
    Note right of Server: 有効期限・権限などを設定
    Server-->>-Client: 4. 事前署名 URL とパラメータを返却
    
    Client->>+S3: 5. 事前署名 URL を使って直接アップロード
    Note right of Client: 事前署名 URL へ POST<br/>fields の全フィールド + ファイル binary を付与
    S3-->>-Client: 6. アップロード完了レスポンス (HTTP 204)
    
    opt ナレッジベースのシーン：ファイルをナレッジベースに登録
        Client->>+Server: 7. fields.key で登録
        Note right of Client: POST /api/v1/knowledge-bases/{KB_ID}/files/<br/>body に file = fields.key を付与
        Server->>Server: 8. KnowledgeBaseFile を作成し解析をスケジュール
        Server-->>-Client: 9. file record を返却
    end
```

#### 従来のアップロードのフロー図

```mermaid
sequenceDiagram
    participant Client as Client
    participant Server as Server
    participant S3 as Storage(S3)

    Note over Client,S3: 従来のアップロードフロー
    
    Client->>+Server: 1. ファイルアップロードリクエスト
    Note right of Client: POST /api/v1/upload<br/>ファイル内容はリクエストに含まれる
    
    Server->>Server: 2. ファイルを検証<br/>(サイズ・タイプ・形式)
    Server->>Server: 3. 一時ファイルを保存
    
    Server->>+S3: 4. ファイルを S3 へアップロード
    Note right of Server: AWS SDK を使用して<br/>一時ファイルをアップロード
    S3-->>-Server: 5. アップロード成功レスポンス
    
    Server->>Server: 6. 一時ファイルをクリーンアップ
    Server-->>-Client: 7. アップロード結果を返却
    Note left of Server: S3 のファイル位置を返却
```

***

#### Presigned ファイルアップロード

以下では、MaiAgent が提供する API を使用してファイルの Presigned アップロードを完了する手順を説明します。**ナレッジベースのシーン**では 3 つのステップ（Step 1 → 2 → 3）をすべて実行する必要があり、メッセージ添付ファイルのシーンでは Step 1 → 2 のみで完了します。

#### 1. **Presigned URL を取得する**

**Endpoint**

`POST https://api.maiagent.ai/api/v1/upload-presigned-url/`

**説明**

クライアントはサーバーにリクエストを送信し、ファイルをクラウドストレージへ直接アップロードするための Presigned URL を取得します。

**リクエストパラメータ**

| パラメータ名      | 型         | 必須 | 説明                                                                                                                                                 |
| ----------- | --------- | -- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `filename`  | `string`  | はい | アップロードするファイルの名前                                                                                                                                    |
| `modelName` | `string`  | はい | <p>モジュール名。アップロードするファイルの用途を分類するために使用します<br></p><p>ナレッジベースの場合は<code>chatbot-file</code>を指定します</p><p>メッセージ添付ファイルの場合は<code>attachment</code>を指定します</p> |
| `fieldName` | `string`  | はい | ファイルフィールド名。ファイルの用途を識別するために使用します                                                                                                                    |
| `fileSize`  | `integer` | はい | ファイルサイズ（バイト単位）。実際の binary サイズと完全に一致している必要があります。一致しない場合、Step 2 で S3 に拒否されます                                                                         |

**リクエスト例**

```bash
curl --location 'https://api.maiagent.ai/api/v1/upload-presigned-url/' \
--header 'Authorization: Api-Key YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
    "filename": "document.pdf",
    "modelName": "chatbot-file",
    "fieldName": "file",
    "fileSize": 178329
}'
```

**レスポンス例**

```json
{
    "url": "https://s3.ap-northeast-1.amazonaws.com/whizchat-media-prod-django.playma.app",
    "fields": {
        "key": "media/chatbots/chatbot-file/86572e41-16ba-45dd-b049-28c69f77ffb0.pdf",
        "x-amz-algorithm": "AWS4-HMAC-SHA256",
        "x-amz-credential": "ASIATIVCN4X5XXXXXXXX/20260522/ap-northeast-1/s3/aws4_request",
        "x-amz-date": "20260522T020727Z",
        "x-amz-security-token": "IQoJb3JpZ2luX2VjEEoa...（とても長い STS token）",
        "policy": "eyJleHBpcmF0aW9uIjog...（base64 policy）",
        "x-amz-signature": "617e10d1db034ab351d3735de5c56287ecc926dbfe5b5884d2ce67deed363004"
    }
}
```

{% hint style="warning" %}
**Production 環境では AWS STS の短期認証情報を使用します**（`x-amz-credential` は `ASIA` で始まります）。レスポンスの `fields` オブジェクトには **`x-amz-security-token`** フィールドが含まれます。Step 2 のアップロード時には、すべての `fields` フィールド（`x-amz-security-token` を含む）を一字一句漏れなく付与する必要があります。漏れがあると S3 に拒否されます。

Presigned URL の**有効期限は約 1 時間**です。取得後はできるだけ早く使用してください。
{% endhint %}

***

#### 2. **ファイルをクラウドストレージへアップロードする**

**説明**

上記のステップで取得した `url` と `fields` を使用して、ファイルをクラウドストレージへ直接アップロードします。**`fields` オブジェクト内のすべてのフィールドを必ず付与してください**（`x-amz-security-token` を含む）。フィールドのリストをハードコードせず、今後 AWS が新しいフィールドを追加した場合でも、動的に組み立てることで漏れを防ぐことができます。

**アップロードが成功すると、S3 は HTTP 204 No Content（空の body）を返します。**

**リクエスト例（curl、STS token を含む）**

```bash
curl --location 'https://s3.ap-northeast-1.amazonaws.com/whizchat-media-prod-django.playma.app' \
--form 'key="media/chatbots/chatbot-file/86572e41-16ba-45dd-b049-28c69f77ffb0.pdf"' \
--form 'x-amz-algorithm="AWS4-HMAC-SHA256"' \
--form 'x-amz-credential="ASIATIVCN4X5XXXXXXXX/20260522/ap-northeast-1/s3/aws4_request"' \
--form 'x-amz-date="20260522T020727Z"' \
--form 'x-amz-security-token="IQoJb3JpZ2luX2VjEEoa..."' \
--form 'policy="eyJleHBpcmF0aW9uIjog..."' \
--form 'x-amz-signature="617e10d1db034ab351d3735de5c56287ecc926dbfe5b5884d2ce67deed363004"' \
--form 'file=@"/path/to/document.pdf"'
```

**リクエスト例（Python、動的に組み立てる、推奨される方法）**

```python
import requests

# Step 1: 取得 Presigned URL
presign = requests.post(
    'https://api.maiagent.ai/api/v1/upload-presigned-url/',
    headers={'Authorization': 'Api-Key YOUR_API_KEY'},
    json={
        'modelName': 'chatbot-file',
        'fieldName': 'file',
        'filename': 'document.pdf',
        'fileSize': 178329,
    },
).json()

# Step 2: 把 fields 整個塞，所有欄位（含 x-amz-security-token）自動帶上
with open('/path/to/document.pdf', 'rb') as f:
    s3_response = requests.post(
        presign['url'],
        data=presign['fields'],
        files={'file': f},
    )
assert s3_response.status_code == 204, s3_response.text

file_key = presign['fields']['key']  # Step 3 要用的值
```

***

#### 3. **ファイルをナレッジベースに登録する（ナレッジベースのシーンのみ必要）**

**Endpoint**

`POST https://api.maiagent.ai/api/v1/knowledge-bases/{knowledgeBasePk}/files/`

**説明**

Step 2 が完了すると、ファイルの binary は S3 に存在しますが、**まだナレッジベースには登録されていません**。この API を呼び出してアップロード結果を `KnowledgeBaseFile` として登録することで、システムが解析・分割・インデックス作成を開始します。

{% hint style="warning" %}
**`file` フィールドには Step 1 のレスポンスの `fields.key`（MaiAgent S3 内部の相対パス）を入力する必要があり、任意の外部 URL ではありません**。外部 URL（例：パートナーシステムのダウンロードリンク）を受け取った場合は、まず `GET` でファイルをダウンロードしてから、Step 1 → 2 → 3 を実行してください。
{% endhint %}

**パスパラメータ**

| パラメータ名            | 型        | 説明                   |
| ----------------- | -------- | -------------------- |
| `knowledgeBasePk` | `string` | ナレッジベースの一意の識別子（UUID） |

**リクエストパラメータ**

| パラメータ名                          | 型        | 必須  | 説明                                                |
| ------------------------------- | -------- | --- | ------------------------------------------------- |
| `files`                         | `array`  | はい  | 作成するファイルのリスト。一度に複数をバッチ作成できます                      |
| `files[].filename`              | `string` | はい  | 元のファイル名                                           |
| `files[].file`                  | `string` | はい  | Step 1 のレスポンスの `fields.key`（相対パス、**URL ではありません**） |
| `files[].parser`                | `string` | いいえ | parser の UUID を指定します。指定しない場合はナレッジベースのデフォルトを使用します  |
| `files[].labels`                | `array`  | いいえ | ファイルラベル（{id, name} オブジェクトの配列）                     |
| `files[].rawUserDefineMetadata` | `object` | いいえ | ユーザー定義の metadata                                  |

**リクエスト例**

```bash
curl --location 'https://api.maiagent.ai/api/v1/knowledge-bases/86401a64-ad89-4847-a709-f4ccfa0af7b9/files/' \
--header 'Authorization: Api-Key YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
    "files": [
        {
            "filename": "document.pdf",
            "file": "media/chatbots/chatbot-file/86572e41-16ba-45dd-b049-28c69f77ffb0.pdf"
        }
    ]
}'
```

**レスポンス例**

```json
[
    {
        "id": "86572e41-16ba-45dd-b049-28c69f77ffb0",
        "filename": "document.pdf",
        "file": "https://media.maiagent.ai/media/chatbots/chatbot-file/86572e41-16ba-45dd-b049-28c69f77ffb0.pdf",
        "fileType": "pdf",
        "knowledgeBase": {
            "id": "86401a64-ad89-4847-a709-f4ccfa0af7b9",
            "name": "私のナレッジベース"
        },
        "size": 178329,
        "status": "initial",
        "parser": {
            "id": "535c5b86-0534-4d0a-abfe-82f3d37e769a",
            "name": "MaiAgent Parser",
            "provider": "maiagent",
            "order": 0,
            "supportsDiarization": false
        },
        "labels": [],
        "rawUserDefineMetadata": {},
        "createdAt": "1779425272000"
    }
]
```

**ファイルステータス（`status`）**

| 値            | 説明              |
| ------------ | --------------- |
| `initial`    | 作成直後、処理待ち       |
| `processing` | 解析・分割・インデックス作成中 |
| `done`       | 処理完了、検索可能       |
| `failed`     | 処理失敗            |

***

## よくあるエラーとトラブルシューティング

**Q：S3 が `The AWS Access Key Id you provided does not exist in our records` を返す**

A：Step 2 で `x-amz-security-token` を付与し忘れているか、期限切れの access key / S3 endpoint をハードコードしています。必ず Step 1 でその都度返される `url` と `fields` を使用し、`fields` オブジェクト全体をそのまま Step 2 に付与してください。

**Q：S3 が `Policy Condition failed` を返す**

A：通常は Step 1 の `fileSize` が実際の binary サイズと一致していないことが原因です。実際のファイルサイズを再計算し、Step 1 をやり直してください。

**Q：Step 3 が 400 を返し、`file` フィールドに問題があると表示される**

A：`file` には Step 1 のレスポンスの `fields.key`（例：`media/chatbots/chatbot-file/xxx.pdf`）を入力する必要があります。Step 3 のレスポンスの full URL でも、任意の外部 URL でもありません。

**Q：すでに外部 URL（例：パートナーシステムのダウンロードリンク）を持っていますが、そのまま Step 3 に渡せますか？**

A：できません。Step 3 の `file` フィールドは MaiAgent 自社 S3 の相対 key です。まず `GET` でその外部 URL のファイルを取得してから、Step 1 → 2 → 3 を実行してください。

**Q：Step 3 の後、ファイルがずっと `status: processing` のままです**

A：解析時間はファイルのサイズやタイプによって異なり、大容量ファイルの場合は数分かかることがあります。`GET /api/v1/knowledge-bases/{KB_ID}/files/{file_id}/` でステータスをポーリングし、`done` になって初めて AI 助理に検索されるようになります。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.maiagent.ai/tech/maiagent-tech-ja/api-integration/api_knowledge.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
