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

# セッショントークンの発行

> Customer がストアで注文を作成するためのセッショントークンを発行する

Customer がストアで注文を作成するための Session Token を発行します。これは **API Key 専用**のエンドポイントです。

```
POST /v1/actions/auth/issue-session-token
```

**認証：** API Key

## 仕組み

1. サーバーが API Key 認証でこのエンドポイントを呼び出します
2. 短命のセッショントークンを受け取ります
3. トークンを customer のブラウザに渡します
4. Customer はトークン（`Authorization: Bearer <token>`）を使用して注文の作成やチェックアウトを行います

Session Token は単一のストアにスコープされ、自動的に有効期限が切れます。

## リクエストボディ

| フィールド           | 型      | 必須  | 説明                                                                         |
| --------------- | ------ | --- | -------------------------------------------------------------------------- |
| `storeId`       | string | No  | 対象ストア ID（Short ID フォーマット `STO_xxx`）。`productId` が指定されていない場合は必須です           |
| `productId`     | string | No  | 商品 ID（Short ID フォーマット `PROD_xxx`）。`storeId` なしで指定した場合、サーバーが商品からストアを自動推定します |
| `buyerIdentity` | string | Yes | 注文帰属のための customer 識別子（例：メールアドレスまたは内部ユーザー ID）。セッション JWT にエンコードされます          |

## リクエスト例

<CodeGroup>
  ```typescript SDK theme={"system"}
  // storeId を使用
  const { token, expiresAt } = await client.auth.issueSessionToken({
    storeId: "STO_2aUyqjCzEIiEcYMKj7TZtw",
    buyerIdentity: "customer@example.com",
  });

  // productId を使用（storeId は自動推定）
  const { token, expiresAt } = await client.auth.issueSessionToken({
    productId: "PROD_7J3K5L8M2N4P6Q9R",
    buyerIdentity: "customer@example.com",
  });
  ```

  ```bash cURL (storeId を使用) theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"storeId":"STO_2aUyqjCzEIiEcYMKj7TZtw","buyerIdentity":"customer@example.com"}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/actions/auth/issue-session-token
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  curl -X POST "https://api.waffo.ai/v1/actions/auth/issue-session-token" \
    -H "Content-Type: application/json" \
    -H "X-Merchant-Id: $MERCHANT_ID" \
    -H "X-Timestamp: $TIMESTAMP" \
    -H "X-Signature: $SIGNATURE" \
    -d "$BODY"
  ```

  ```bash cURL (productId を使用) theme={"system"}
  MERCHANT_ID="MER_2aUyqjCzEIiEcYMKj7TZtw"
  TIMESTAMP=$(date +%s)
  BODY='{"productId":"PROD_7J3K5L8M2N4P6Q9R","buyerIdentity":"customer@example.com"}'
  BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -binary | base64 -w 0)
  CANONICAL_REQUEST="POST
  /v1/actions/auth/issue-session-token
  $TIMESTAMP
  $BODY_HASH"

  SIGNATURE=$(echo -n "$CANONICAL_REQUEST" | openssl dgst -sha256 -sign private_key.pem | base64 -w 0)

  curl -X POST "https://api.waffo.ai/v1/actions/auth/issue-session-token" \
    -H "Content-Type: application/json" \
    -H "X-Merchant-Id: $MERCHANT_ID" \
    -H "X-Timestamp: $TIMESTAMP" \
    -H "X-Signature: $SIGNATURE" \
    -d "$BODY"
  ```

  ```python Python theme={"system"}
  # storeId を使用
  result = call_api_with_signature('POST', '/v1/actions/auth/issue-session-token', {
      'storeId': 'STO_2aUyqjCzEIiEcYMKj7TZtw',
      'buyerIdentity': 'customer@example.com'
  })

  # productId を使用
  result = call_api_with_signature('POST', '/v1/actions/auth/issue-session-token', {
      'productId': 'PROD_7J3K5L8M2N4P6Q9R',
      'buyerIdentity': 'customer@example.com'
  })
  print(result['data']['token'])
  ```
</CodeGroup>

## 成功レスポンス (200)

```json theme={"system"}
{
  "data": {
    "token": "opaque-session-token...",
    "expiresAt": "2024-01-15T11:00:00.000Z"
  }
}
```

## レスポンスフィールド

| フィールド       | 型      | 説明             |
| ----------- | ------ | -------------- |
| `token`     | string | Session Token  |
| `expiresAt` | string | 有効期限（ISO 8601） |

## エラー

> **リトライポリシー**：4xx は一切リトライしない — リクエストを修正してから再送信。5xx は指数バックオフでリトライ（5s 開始、最大 3 回）。

| ステータス | `errors[0].message`                                       | 意味                               | 推奨処理                          |
| ----- | --------------------------------------------------------- | -------------------------------- | ----------------------------- |
| 400   | `Missing required field: buyerIdentity`                   | `buyerIdentity` が欠落または空          | リクエストボディを修正してから再送信            |
| 400   | `Missing required field: provide storeId or productId`    | `storeId` と `productId` のいずれも未指定 | いずれかを指定してから再送信                |
| 400   | `Expected format: STO_xxx, got "..."`                     | `storeId` Short ID のデコード失敗       | `storeId` のフォーマットを修正してから再送信   |
| 400   | `Expected format: PROD_xxx, got "..."`                    | `productId` Short ID のデコード失敗     | `productId` のフォーマットを修正してから再送信 |
| 400   | `Store is not active`                                     | ストアは存在するが `active` 状態ではない        | ストアを有効化してから再送信                |
| 401   | `Missing merchantId in request context`                   | API Key 認証で merchant が解決されなかった   | API Key ヘッダーと署名を確認            |
| 403   | `Access denied: you do not have permission to this store` | マーチャントがストアを所有していない               | ストアの所有権を確認                    |
| 404   | `Store not found`                                         | ストアが存在しないか削除済み                   | store ID を確認                  |
| 404   | `Product not found`                                       | 商品が存在しない                         | product ID を確認                |
| 500   | `Internal server error`                                   | サーバ側の予期しない障害                     | 指数バックオフでリトライ（5s 開始、最大 3 回）    |
