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

# 画像アップロード

> 画像をアップロードしてURLを取得、画像/動画生成APIで使用

<Note>
  **ドキュメントPlaygroundはファイルアップロードに対応していません**：下記のcURL、Python、またはJavaScriptのコード例を使用してテストしてください。
</Note>

<Warning>
  **重要な変更：** パフォーマンスとコスト管理の向上のため、生成APIでのbase64画像データの直接送信はサポートを終了しました。本APIで画像をアップロードし、URLを取得してから生成APIを呼び出してください。
</Warning>

## なぜ先に画像をアップロードする必要がありますか？

1. **パフォーマンス最適化** - base64エンコードはデータを33%膨張させます。先にアップロードすることでリクエストボディのサイズを大幅に削減できます
2. **画像の再利用** - 一度アップロードすれば、URLを何度でも使用でき、重複転送が不要です

## 使用フロー

```mermaid theme={null}
sequenceDiagram
    participant クライアント
    participant APIMart
    participant ストレージ

    クライアント->>APIMart: POST /v1/uploads/images (画像ファイルをアップロード)
    APIMart->>ストレージ: 画像を保存
    ストレージ-->>APIMart: ストレージパスを返却
    APIMart-->>クライアント: 画像URLを返却
    クライアント->>APIMart: POST /v1/images/generations (画像URLを使用)
```

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/v1/uploads/images \
    --header 'Authorization: Bearer <token>' \
    --form 'file=@/path/to/your/image.jpg'
  ```

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

  # 画像をアップロード
  with open('image.jpg', 'rb') as f:
      response = requests.post(
          "https://api.apimart.ai/v1/uploads/images",
          headers={
              "Authorization": "Bearer <token>"
          },
          files={
              "file": f
          }
      )

  result = response.json()
  image_url = result['url']
  print(f"画像URL: {image_url}")

  # アップロードした画像を使用して生成
  response = requests.post(
      "https://api.apimart.ai/v1/images/generations",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json={
          "model": "gemini-3-pro-image-preview",
          "prompt": "この画像を基にバリエーションを作成",
          "image_urls": [{"url": image_url}]
      }
  )
  ```

  ```javascript JavaScript theme={null}
  // 画像をアップロード
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);

  const uploadResponse = await fetch('https://api.apimart.ai/v1/uploads/images', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <token>'
    },
    body: formData
  });

  const uploadResult = await uploadResponse.json();
  const imageUrl = uploadResult.url;
  console.log(`画像URL: ${imageUrl}`);

  // アップロードした画像を使用して生成
  const genResponse = await fetch('https://api.apimart.ai/v1/images/generations', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <token>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gemini-3-pro-image-preview',
      prompt: 'この画像を基にバリエーションを作成',
      image_urls: [{url: imageUrl}]
    })
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "url": "https://upload.apimart.ai/f/image/9990000123456-a1b2c3d4-photo.jpg",
    "filename": "photo.jpg",
    "content_type": "image/jpeg",
    "bytes": 235680,
    "created_at": 1743436800
  }
  ```

  ```json 400 - ファイルフィールドが不足 theme={null}
  {
    "error": {
      "message": "missing or invalid file field: http: no such file",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 400 - サポートされていない形式 theme={null}
  {
    "error": {
      "message": "unsupported image type: application/pdf, allowed: jpeg, png, gif, webp",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 413 - ファイルサイズ超過 theme={null}
  {
    "error": {
      "message": "file size 25165824 exceeds maximum 20971520 bytes",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 429 - レート制限超過 theme={null}
  {
    "error": {
      "code": 429,
      "message": "Rate limit exceeded. Please try again later",
      "type": "rate_limit_error"
    }
  }
  ```

  ```json 500 - アップロード失敗 theme={null}
  {
    "error": {
      "message": "failed to upload image",
      "type": "server_error"
    }
  }
  ```
</ResponseExample>

## Authorizations

<ParamField header="Authorization" type="string" required>
  すべてのAPIはBearer Token認証が必要です

  API Keyの取得：

  [API Key管理ページ](https://apimart.ai/keys)にアクセスしてAPI Keyを取得してください

  リクエストヘッダーに追加：

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

## Body

<ParamField body="file" type="file" required>
  画像ファイル

  対応形式：JPEG (.jpg, .jpeg)、PNG (.png)、WebP (.webp)、GIF (.gif)

  最大ファイルサイズ：20MB
</ParamField>

## Response

<ResponseField name="url" type="string">
  画像の公開アクセスURL、生成APIで直接使用可能（72時間有効）
</ResponseField>

<ResponseField name="filename" type="string">
  元のファイル名
</ResponseField>

<ResponseField name="content_type" type="string">
  検出されたMIMEタイプ、例：`image/jpeg`
</ResponseField>

<ResponseField name="bytes" type="integer">
  ファイルサイズ（バイト）
</ResponseField>

<ResponseField name="created_at" type="integer">
  アップロード時間のUnixタイムスタンプ（秒）
</ResponseField>

## 完全な例：画像生成ワークフロー

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

API_KEY = "your-Apimart-key"
BASE_URL = "https://api.apimart.ai"

# ステップ1：参照画像をアップロード
def upload_image(file_path):
    with open(file_path, 'rb') as f:
        response = requests.post(
            f"{BASE_URL}/v1/uploads/images",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": f}
        )
    return response.json()['url']

# ステップ2：生成タスクを作成
def create_generation(image_url, prompt):
    response = requests.post(
        f"{BASE_URL}/v1/images/generations",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "model": "gemini-3-pro-image-preview",
            "prompt": prompt,
            "image_urls": [{"url": image_url}],
            "size": "16:9"
        }
    )
    return response.json()['id']

# ステップ3：タスクステータスをポーリング
def wait_for_result(task_id):
    while True:
        response = requests.get(
            f"{BASE_URL}/v1/images/generations/{task_id}",
            headers={"Authorization": f"Bearer {API_KEY}"}
        )
        result = response.json()

        if result['status'] == 'completed':
            return result['url']
        elif result['status'] == 'failed':
            raise Exception(f"生成失敗: {result.get('fail_reason')}")

        time.sleep(2)

# ワークフローを実行
image_url = upload_image("reference.jpg")
print(f"画像アップロード完了: {image_url}")

task_id = create_generation(image_url, "この写真をジブリアニメ風に変換")
print(f"タスク作成完了: {task_id}")

result_url = wait_for_result(task_id)
print(f"生成完了: {result_url}")
```
