
# サインイントランザクションを作成

`POST /fapi/v1/transactions` · 環境のサインインホストから呼び出されます

アプリケーションのサインイントランザクションを開始します。ホスト型サインインページ、UI コンポーネント、ヘッドレスクライアントは、環境のサインインホスト（`keenauth.app` のサブドメインまたは確認済みのカスタムドメイン）でこのエンドポイントを呼び出します。レスポンスでは、トランザクション Cookie `__Host-idp_ltx`（Secure、HttpOnly、SameSite=Lax、有効期間 15 分）が設定され、後続の手順はこの Cookie を使用します。

## リクエスト

ヘッダー:

| Header | Required | Description |
| --- | --- | --- |
| `Idp-Client` | yes | SDK 識別子。形式は `<package>/<version> (<runtime>/<version>)` です。 |
| `Origin` | yes | 正確に `https://<sign-in host>` である必要があります。 |

ボディ:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `client_id` | string | yes | アプリケーションのクライアント ID。 |
| `redirect_uri` | string (URI) | yes | アプリケーションに登録済みのリダイレクト URI のいずれか。 |

## レスポンス

`201 Created` でトランザクションオブジェクトを返します:

```json
{
  "schema_version": 1,
  "state": "identifier_pending",
  "next_steps": [{ "step": "identifier", "fields": ["identifier"] }],
  "csrf_token": "<token>",
  "expires_at": "2026-10-05T10:15:00Z"
}
```

このトランザクションの状態を変更するすべてのリクエストでは、`csrf_token` を `Idp-Csrf-Token` ヘッダーで送り返してください。

認可リクエストで SSO が必要な組織が指定されている場合、回答はすでに `federated_redirect` と `redirect_url` になっている場合があります（接続が 1 つの場合: トップレベルウィンドウをそこへ移動してください）。または `sso_connections` を含む場合があります（複数の場合: `sso_start` 手順で選択内容を送信してください）。

## DPoP にバインドされたヘッドレストランザクション

自社のオリジンで動作するファーストパーティの SPA またはネイティブアプリは、`DPoP` ヘッダー（RFC 9449）を付けてヘッドレスサインインを開始します。このプルーフは、クライアントが保持する鍵（ブラウザーでは抽出不可の WebCrypto 鍵、デバイスではプラットフォームの鍵ストア）で署名され、`htm` は `POST`、`htu` は `https://<sign-in host>/fapi/v1/transactions` です。トランザクションは Cookie ではなくその鍵にバインドされます。この場合 Cookie は設定されず、オブジェクトに `csrf_token` は含まれません。トランザクションの後続のすべてのリクエストでは、同じ鍵から新しいプルーフを送信してください。

認可エンドポイントのルールで検証される追加のボディフィールド:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code_challenge` | string | yes | PKCE S256 チャレンジ（RFC 7636）。 |
| `code_challenge_method` | string | yes | `S256`。 |
| `scope` | string | no | スペース区切りのスコープ（例: `openid profile email offline_access`）。 |
| `state` | string | no | 認可コードとともに返されます。 |
| `nonce` | string | no | ID トークンの `nonce`。 |
| `organization` | string | no | 組織の ID または名前。 |
| `ui_locales` | string | no | 優先言語。 |
| `resource` | string (URI) | no | リソースインジケーター（RFC 8707）。 |

`Origin` はサインインホスト、またはアプリケーションの許可された Web オリジンのいずれかです。ネイティブアプリは何も送信しません。開始できるのはファーストパーティのアプリケーションだけです。認可エンドポイントが拒否したフィールドは、`422 validation_failed` を返し、`errors[].code` に OAuth エラーコードが含まれます。サーバーが `401 use_dpop_nonce` を返した場合は、`DPoP-Nonce` レスポンスヘッダーの値を使って新しいプルーフに署名し、再試行してください。`DPoP` ヘッダーなしでこれらのフィールドを送信すると、`422 validation_failed`（`dpop_required`）を返します。

## 組織の切り替え

サインイン中のユーザーのフロント API アクセストークンを保持しているアプリケーション（[フロント API アクセストークン](/docs/api/fapi/front-api-token) を参照）は、画面を表示せずにユーザーを別の組織へ切り替えられます。トークンを `Authorization: DPoP <token>` で送信し、トークンの鍵のプルーフ（`ath` を含む）を添えてください。ボディには `flow` に `organization_switch` を指定し、上記の DPoP バインドされたヘッドレスフィールド（トークンのアプリケーションの `client_id`、`redirect_uri`、`code_challenge`、`state`、`nonce`、`scope`）と、`GET /fapi/v1/me/organizations` から取得した組織の `org_…` ID である `organization` を含めます。

このリクエストは、セッションを再利用するサインインと同様に、トークンのセッションを使って直ちに判定されます。判定対象は、組織のポリシー（MFA、アイドル制限、SSO、IP リスト）、同意、保留中の法的文書です。回答は `201` で、`authorization_response` を含む `completed` トランザクションです。その `code` を、`code_verifier` と同じ鍵のプルーフとともにトークンエンドポイントで交換してください。新しいトークンには `org_id` に組織が含まれます。開いたままのトランザクションは残らず、Cookie も設定されません。

```json
{
  "schema_version": 1,
  "state": "completed",
  "next_steps": [],
  "authorization_response": { "code": "<code>", "state": "<state>", "iss": "https://example.keenauth.app" },
  "expires_at": "2026-10-05T10:15:00Z"
}
```

| Status | Code | When |
| --- | --- | --- |
| 401 | `unauthenticated` | トークンが無効、期限切れ、取り消し済み、または鍵にバインドされていない、そのアプリケーションが有効なファーストパーティアプリケーションでない、またはそのセッションが終了している。 |
| 422 | `validation_failed` | `flow` が `organization_switch` でない、`client_id` がトークンのアプリケーションでない、`organization` が `org_…` ID でない、またはこのアプリケーションでユーザーがその組織へ切り替えられない（`not_eligible`）。 |
| 403 | `authorization_failed` | 組織が切り替えでは表示できない画面を必要とする。`error` は OAuth エラー（`login_required`、`interaction_required`、`consent_required`）。`organization` を設定して新しいサインインを開始してください。 |

トークンなしで `flow` に `organization_switch` を指定すると、`422 validation_failed`（`access_token_required`）を返します。

## エラー

| Status | Code | When |
| --- | --- | --- |
| 400 | `malformed_request` | `Idp-Client` がないか、ボディが有効な JSON ではない。 |
| 403 | `origin_not_allowed` | `Origin` がサインインホストではない。 |
| 403 | `headless_not_allowed` | サードパーティのアプリケーションがヘッドレスフローを開始しようとした。 |
| 404 | `not_found` | ホストがどの環境のサインインホストでもない。 |
| 422 | `validation_failed` | `client_id` がこの環境のアプリケーションではない、`redirect_uri` がそのアプリケーションに登録されていない、またはフィールドが無効。 |
| 401 | `invalid_dpop_proof` | `DPoP` プルーフがない、無効、または再利用されている、またはホストが DPoP にバインドされたトランザクションを提供していない。 |
| 401 | `use_dpop_nonce` | `DPoP-Nonce` レスポンスヘッダーの値を使って新しいプルーフに署名してください。 |
| 503 | `temporarily_unavailable` | 依存先が利用できない。後で再試行してください。 |

## 例

```bash
curl -X POST https://example.keenauth.app/fapi/v1/transactions \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"client_id":"<client_id>","redirect_uri":"https://app.example.com/callback"}'
```

## 個人データ

このエンドポイントは個人データを扱います: エンドユーザーのプロフィール。[KeenAuth API の個人データ](/docs/policies/personal-data) では、保存される内容、保存期間、削除方法を説明しています。特別な種類の個人データ（健康、生体データ、宗教、政治的意見、性的指向）はどのフィールドにも送信しないでください。
