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

# Blob アップロードトークン

> POST /v1/upload-tokens で短期間有効なアップロードトークンを発行し、ブラウザが API キーなしで Blob Storage に直接アップロードできるようにします。

<ParamField header="Authorization" type="string" placeholder="API Key" required>
  アカウントの API キーです。これは[アカウント設定](https://squarecloud.app/ja/account/security)で確認できます。
</ParamField>

アップロードトークンを使うと、**サーバー**が短期間有効なトークンを発行し、**ブラウザ**やモバイルアプリがそれを使って Blob Storage に直接アップロードできます。ファイルがサーバーを経由することはなく、API キーがサーバーの外に出ることもありません。`blob:write` スコープと有料プランが必要です。

トークンは[オブジェクトのアップロード](/ja/blob-reference/endpoint/post)または[チャンクアップロード](/ja/blob-reference/endpoint/chunked-init)のルートの `Authorization` ヘッダーで送信し、それ以外では機能しません (`403 UPLOAD_TOKEN_NOT_ALLOWED`)。発行時に設定したものはすべて**固定されます**: ブラウザは名前、プレフィックス、公開範囲、有効期限、メタデータを変更したり、より大きなファイルを送信したり、別のファイル形式を使用したりすることはできません。

* アップロードごとに 1 回分を消費します: オブジェクトのアップロードの呼び出し 1 回、またはチャンクアップロードの開始 1 回です (そのパートの送信と完了で追加の消費はありません)。
* `name` を指定しない場合はブラウザが名前を選び、その名前には常にセキュリティハッシュが付与されるため、トークンが漏えいしても既存のファイルが置き換えられることはありません。
* トークンは、使用回数を使い切ったとき (`401 UPLOAD_TOKEN_USED`)、有効期限が切れたとき、または発行元の API キーが取り消されたとき (`401 ACCESS_DENIED`) に機能しなくなります。

<ParamField body="name" type="string">
  ファイル名を固定します。指定しない場合、ブラウザがクエリで `name` を送信します。
</ParamField>

<ParamField body="prefix" type="string">
  プレフィックスを固定します。異なるプレフィックスを送信したブラウザは `403 PREFIX_NOT_ALLOWED` を受け取ります。
</ParamField>

<ParamField body="private" type="boolean">
  公開範囲を固定します。
</ParamField>

<ParamField body="security_hash" type="boolean">
  `name` を指定した場合のみ: `false` にすると、アップロードでその名前のファイルを置き換えられます。それ以外の場合、名前には常にハッシュが付与されます。
</ParamField>

<ParamField body="expire" type="string | null">
  有効期限を固定します (`30d`、`6h`)。有効期限なしの場合は `null`。7 日未満には Enterprise が必要です。
</ParamField>

<ParamField body="max_size" type="number">
  最大ファイルサイズ (バイト)。512〜10737418240 (10 GiB) です。
</ParamField>

<ParamField body="allowed_extensions" type="string[]">
  受け付ける拡張子。1〜20 個、小文字でドットなし (`png`、`tar.gz`) です。
</ParamField>

<ParamField body="metadata" type="object">
  トークンでアップロードされるすべてのファイルに追加されるメタデータ。Pro と Enterprise のみ。
</ParamField>

<ParamField body="expires_in" type="number" default="900">
  トークンの有効期間。60〜3600 秒です。
</ParamField>

<ParamField body="max_uses" type="number" default="1">
  トークンで許可されるアップロード回数。1〜100 です。
</ParamField>

### レート制限

<Note>1 分間に 120 トークン (`RATE_LIMITED`、429)。発行時には何も保存されないため、エンドユーザーのアップロードごとに 1 つのトークンを発行しても問題ありません。</Note>

### レスポンス

<ResponseField name="status" type="string">
  成功した場合は "success"、失敗した場合は "error" です。
</ResponseField>

<ResponseField name="response" type="object">
  <Expandable title="オブジェクトを切り替え">
    <ResponseField name="token" type="string">
      アップロードトークン (`squp_...`)。これをブラウザに渡します。
    </ResponseField>

    <ResponseField name="expires_at" type="ISO 8601">
      トークンの有効期限。
    </ResponseField>

    <ResponseField name="max_uses" type="number">
      トークンで許可されるアップロード回数。
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```javascript サーバー (Node.js) theme={null}
  // Your backend: mint a token for the signed-in user and return it to the page.
  const res = await fetch('https://blob.squarecloud.app/v1/upload-tokens', {
    method: 'POST',
    headers: {
      Authorization: process.env.SQUARE_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      prefix: `avatars/${userId}`,
      allowed_extensions: ['png', 'jpg', 'webp'],
      max_size: 2 * 1024 * 1024,
      expires_in: 300,
    }),
  });
  const { response } = await res.json();
  // send response.token to the browser
  ```

  ```javascript ブラウザ theme={null}
  const form = new FormData();
  form.append('file', input.files[0]);

  const res = await fetch('https://blob.squarecloud.app/v1/objects?name=avatar', {
    method: 'POST',
    headers: { Authorization: token },
    body: form,
  });
  const { response } = await res.json();
  // response.url is the public URL of the new file
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://blob.squarecloud.app/v1/upload-tokens' \
    --header 'Authorization: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{ "prefix": "avatars", "allowed_extensions": ["png", "jpg"], "max_size": 2097152 }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "status": "success",
    "response": {
      "token": "squp_Tq7xLm2Vb9Rk4Wz1Nc8Hy5Js0Gd3Fp6Ae.Hq3mZ8vT1kLw9xRb",
      "expires_at": "2026-09-25T12:15:00.000Z",
      "max_uses": 1
    }
  }
  ```
</ResponseExample>

### エラー

| コード                                                                                                                                                               | HTTP | 発生する状況                                          |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------- |
| `INVALID_BODY`                                                                                                                                                    | 400  | 本文が JSON オブジェクトではない。                            |
| `INVALID_OBJECT_NAME` / `INVALID_OBJECT_PREFIX` / `INVALID_OBJECT_PRIVATE` / `INVALID_OBJECT_SECURITY_HASH` / `INVALID_OBJECT_EXPIRE` / `INVALID_OBJECT_METADATA` | 400  | 固定する値が無効。                                       |
| `INVALID_MAX_SIZE` / `INVALID_ALLOWED_EXTENSIONS` / `INVALID_EXPIRES_IN` / `INVALID_MAX_USES`                                                                     | 400  | 制限値が範囲外。                                        |
| `UPLOAD_TOKEN_TOO_LARGE`                                                                                                                                          | 400  | 1 つのトークンに対してオプションが多すぎる。メタデータまたは拡張子リストを短くしてください。 |
| `PERMISSION_DENIED`                                                                                                                                               | 401  | アカウントに有効な有料プランがない。                              |
| `UPGRADE_REQUIRED`                                                                                                                                                | 403  | 有効期限またはメタデータに上位のプランが必要。                         |
| `RATE_LIMITED`                                                                                                                                                    | 429  | 1 分間に 120 トークンを超えた。                             |

ブラウザがアップロードする際のエラー: `401 UPLOAD_TOKEN_USED` (使い切った)、`401 ACCESS_DENIED` (期限切れまたは取り消し済み)、`403 PREFIX_NOT_ALLOWED` (別のプレフィックス)、`400 FILE_TYPE_NOT_ALLOWED` (許可されていない拡張子)、`413 FILE_TOO_LARGE` (`max_size` 超過)。
