# POST /api/files

アップロード先発行

ファイルのアップロード先と、そのファイルを利用するための `file_id` を発行します。
ファイル本体は、発行された送信先へアップロードできます。

ファイルを利用するまでの手順は次のとおりです。

1. 用途を指定してこのエンドポイントを呼び出し、`upload_url`、`upload_fields`、`file_id` を取得します。
2. `upload_url` へ、`upload_fields` のすべての項目とファイル本体を `multipart/form-data` で POST します。
3. 送信に成功したら、商品画像の追加などのエンドポイントに `file_id` を渡します。

`file_id` の利用には、次の制約があります。

- `file_id` の発行だけでは、ファイルのアップロードは完了しません。
- 発行時に指定した用途と異なる用途には使えません。
- 宣言した形式とファイルの中身が異なる場合、アップロードには成功しても、`file_id` を渡した先で拒否されます。

アップロード先の応答は、ステータスコードが 2xx なら成功です。
応答の本文から取り出して使う値はありません。
アップロード先は BASE API のエラー形式（`application/problem+json`）を返さないため、ステータスコードで成否を判断してください。

アップロード先の発行には、用途によらず `files.write` スコープが必要です。
ファイルを利用する操作には、その操作のスコープも必要です。

## 要求スコープ

- `files.write`

## リクエストボディ

`application/json`

`purpose` の値により分岐します。

- ItemImageUploadInput の場合
  - `purpose` "item_image"（必須）: アップロードするファイルの用途。`item_image` は商品画像です。
  - `content_type` "image/gif" | "image/jpeg" | "image/png"（必須）: アップロードする画像の形式。ここで宣言した値と異なる形式を送信時に指定すると拒否されます。ファイルの中身は送信の時点では確認されないため、宣言と中身が食い違うファイルは送信に成功しますが、`file_id` を渡した先で拒否されます。

## レスポンスボディ（200）

`application/json`

- `file_id` string（必須 / 1 文字以上）: アップロードするファイルの参照。送信が完了したあと、このファイルを使うエンドポイント（商品画像の追加など）へそのまま渡します。内容を解釈せず、受け取った文字列のまま保持してください。
- `file_expires_at` string (date-time)（必須）: ファイルの参照が使える期限。この時刻を過ぎると `file_id` は受け付けられません。この期限は、まだどこにも登録していないファイルに対するものです。商品画像などに登録したあとのファイルは、この期限の影響を受けません。`upload_expires_at` は必ずこの時刻以前です。
- `upload_url` string (uri)（必須）: ファイル本体の送信先。BASE API ではなくファイルの保管先を指します。この URL へ multipart/form-data で送信してください。
- `upload_fields` object（必須）: ファイル本体と一緒に送信する値の組。すべての項目を、キーと値をそのまま multipart/form-data のフィールドとして送信してください。値を変更したり、一部を省略したりすると送信が拒否されます。ファイル本体は、これらの項目をすべて並べたあと、最後の `file` フィールドとして送信してください。
  - （プロパティ定義なし）
- `upload_expires_at` string (date-time)（必須）: ファイル本体を送信できる期限。この時刻を過ぎると送信できなくなります。送信を終えたファイルは `file_expires_at` まで使えます。
- `max_bytes` integer（必須 / ≥ 0）: 送信できるファイルの最大バイト数。用途によって異なります。これを超えるファイルは送信時に拒否されます。

## リクエスト例

```sh
curl -X POST "https://apiv2.thebase.com/api/files" \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -d '{
  "purpose": "item_image",
  "content_type": "image/gif"
}'
```

## レスポンス

| Status | Description |
| --- | --- |
| `200` | 発行成功。アップロード先とファイルの参照を返します。 |

## エラー

エラーは `application/problem+json` の Problem 形式で返します。認証・スコープ・予期しない内部エラーなど、すべてのエンドポイントに共通のエラーと構造・判別方法は [エラーレスポンス](/docs/errors.md) を参照してください。

このエンドポイントが返すその他のエラーは次のとおりです。

| Status | Type | Description |
| --- | --- | --- |
| `400` | `/errors/request/malformed-body` | リクエストボディをこのエンドポイントが要求する形式として解釈できない場合に返します。 |
| `400` | `/errors/files/invalid-body` | リクエストボディがエンドポイントのスキーマを満たさない場合に返します。 |
| `413` | `/errors/request/body-too-large` | JSON リクエストボディが 1 MiB の上限を超える場合に返します。 |
| `415` | `/errors/request/unsupported-media-type` | JSON 形式のリクエストボディを要求するエンドポイントに、対応していない Content-Type が指定された、または Content-Type が指定されていない場合に返します。 |
| `502` | `/errors/internal/bad-gateway` | BASE API が処理を完了するために必要な内部処理で不整合が発生した場合に返します。 |
| `504` | `/errors/internal/gateway-timeout` | BASE API が処理を完了するために必要な内部処理が制限時間内に完了しなかった場合に返します。 |

