検証済み保護者リンク
検証済み保護者リンク(VPL)は、プレイヤーが自分の保護者をプロダクトに招待できるようにする仕組みです。プレイヤーが招待を送り、保護者が本人確認を済ませると、それ以降その保護者はプレイヤーのコントロールを確認し設定できるようになります。招待が保留のあいだもプロダクト内で何かがブロックされることはなく、保護者が承諾しなくても何も壊れません。
このガイドでは、セッションの作成、招待の送信、状態の追跡、招待のキャンセル、そしてどちらの側からのリンク解除も含めたフロー全体を説明します。
検証済み保護者リンク(VPL)では、VPLがゲートではなくリンクである理由と、VPCと相互に排他的である理由を説明しています。そこで述べている適格性のルールが、このガイドの呼び出しが成功するかどうかを決めます。
前提条件
始める前に次のものが必要です。
- k-IDプロダクト: Compliance Studioでプロダクトを作成して設定します。
- APIキー: プロダクトのDeveloper Settingsページで発行します。このガイドの呼び出しはすべてサーバー間通信です。認証を参照してください。
- ウェブフックのエンドポイント:
Challenge.StateChangeとSession.Unlinkを受け取るHTTPSエンドポイント。ウェブフックを参照してください。 - 処理するイベントの購読: エンドポイントが受け取れるのは購読しているイベントタイプだけで、それ以外はk-IDが配信も試みずエラーも返さずに破棄します。Compliance StudioのプロダクトのDeveloper Settingsページで、対象のエンドポイントに
Challenge.StateChangeとSession.Unlinkを選択してください。 - 組織でVPLが有効になっていること: k-IDに連絡して、この機能を組織で有効化してもらってください。
以下の例はすべて、ライブモードのベースURLhttps://game-api.k-id.com/api/v1、Content-Type: application/json、Authorization: Bearer <api-key>ヘッダーを使います。テストモードではhttps://game-api.test.k-id.com/api/v1を使ってください。
ステップ1: プレイヤーのセッションを作成する
POST /age-gate/checkを呼び出して、プレイヤーのセッションを作成します。
POST /age-gate/check
{
"jurisdiction": "US-CA",
"age": 17
}
age、dateOfBirth、kuid(kuidをキャッシュしている再訪プレイヤーの場合)のうち、渡すのは多くとも1つです。複数を渡した場合は400が返ります。このエンドポイントが受け付ける他の年齢シグナルについては/age-gate/checkを参照してください。
成功時のレスポンスにはセッションが含まれます。
{
"status": "PASS",
"session": {
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"status": "ACTIVE",
"managedBy": "PLAYER",
"hasApproverEmail": false
}
}
sessionIdを自分のユーザーレコードに保存してください。このガイドのすべての呼び出しはこれをキーにしており、リンク、リンク解除、再リンクをまたいでも変わりません。
ステータスがPASSではなくCHALLENGEの場合、プレイヤーはその管轄区域のアクセス年齢未満であり、保護者の同意が必要です。VPCへ誘導し、招待エンドポイントは呼び出さないでください。保護者を招待する対象となるセッションが存在しないためです。
PASSが返ったセッションでも、GUARDIAN管理の権限を持っていればVPLの対象外です。招待の導線を表示する前にセッションのpermissions[]を確認するか、ステップ3のFEATURE_DISABLEDエラーを処理してください。
ステップ2: 招待の導線を表示する
設定画面、プレイヤーのプロフィール、オンボーディングなど、プロダクトに合う場所に配置してください。プレイヤーがタップしたら、保護者のメールアドレスを収集します。
VPLはオプトインでブロックしない仕組みなので、これは割り込み画面ではなく通常のプロダクト導線として扱えます。プレイヤーはいつまでも無視して構いません。
ステップ3: 招待を送る
POST /challenge/invite-parentを呼び出します。
POST /challenge/invite-parent
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"parentEmail": "parent@example.com",
"playerName": "Alex",
"locale": "en"
}
| フィールド | 必須 | 説明 |
|---|---|---|
sessionId | はい | ステップ1のセッション |
parentEmail | はい | 招待の送信先 |
playerName | いいえ | プレイヤーの表示名。1〜63文字。招待メールで保護者に表示されます。省略すると汎用のプレースホルダーが表示されます |
locale | いいえ | 招待メールのIETF BCP 47タグ。省略した場合、k-IDはその保護者をすでに把握していればその保護者自身の登録言語を使い、次にプロダクトの主要言語、最後に英語にフォールバックします |
{
"status": "CHALLENGE",
"challenge": {
"challengeId": "ae6d4729-af32-42ea-8ef2-ff46c7664802",
"type": "CHALLENGE_PARENT_INVITE"
}
}
1回の呼び出しでチャレンジの作成、セッションへの紐づけ、メール送信までが行われます。メール送信のための追加の呼び出しは不要で、/challenge/send-emailは保護者招待チャレンジを拒否します。
challengeIdはセッションと合わせて保存してください。ウェブフック、ステータスエンドポイント、キャンセルの呼び出しで、この招待を特定するために使います。
保留中の招待のchallengeIdを保持しているあいだは、同じセッションに対して別のメールアドレス宛の招待を送らないでください。
招待メール内のリンクは、ライブモードでは14日間、テストモードでは待たずに期限切れを試せるよう7分間有効です。
処理すべきエラー
エラーはHTTP 400で返り、レスポンスボディのerrorフィールドにコードが入ります。
| コード | 発生する状況 | 対応 |
|---|---|---|
FEATURE_DISABLED | Verified parent linking is not enabled。組織でVPLが無効 | k-IDに連絡する |
FEATURE_DISABLED | Verified parent linking is not available for this player。プレイヤーがアクセス年齢未満、またはセッションにGUARDIAN管理の権限がある | VPCにフォールバックする。このセッションでは招待の導線を表示しない |
NOT_FOUND | セッションが存在しない | 保存しているsessionIdを確認する |
INVALID_INPUT | セッションの管轄区域がプロダクトに設定されていない | Compliance Studioでプロダクト設定を修正する |
INVALID_EMAIL | Session is not eligible for a new invite。すでに保護者がリンク済み | 現在のリンク状態を表示する |
ステップ4: ブロックせずに待つ
招待が保留のあいだも、プロダクトは完全に利用できる状態を保ってください。プレイヤーはすでに年齢ゲートを通過しており、招待によってできることが変わるわけではありません。
保護者がフローを完了すると、k-IDはあなたのウェブフックエンドポイントにChallenge.StateChangeを送信します。
{
"eventType": "Challenge.StateChange",
"data": {
"id": "ae6d4729-af32-42ea-8ef2-ff46c7664802",
"productId": 12345,
"type": "CHALLENGE_PARENT_INVITE",
"status": "PASS",
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"approverEmail": "parent@example.com",
"kuid": "12b9fa0e-6d6d-4903-a1fc-f2233027b71d"
}
}
受信したら次を行います。
data.idとdata.sessionIdを、保存しているプレイヤーレコードと突き合わせます。kuidをキャッシュします。これは、このセッションに保護者がリンクされていることを示します。- 保護者が接続されていることをUIに反映します。
招待がキャンセルされた場合は、同じイベントがstatus: FAILで届きますが、FAILのペイロードにはsessionIdが含まれません。data.sessionIdではなく、保存しておいたchallengeIdとdata.idを突き合わせてください。そうしないとハンドラーはキャンセルをすべて取りこぼします。保護者が接続されていない状態として扱ってください。プレイヤーは改めて招待を送れます。
保護者が承諾しない場合、以降のイベントは届かず何も変わりません。
ステップ5: 現在の状態を必要に応じて確認する
状態遷移の正となるのはウェブフックですが、プレイヤーがアプリを開き直したときなど、待たずに現在の状態が必要になる場面もあります。
いま保護者はリンクされているか
sessionIdを指定してGET /session/getを呼び出し、次の2つのフィールドを読みます。
hasApproverEmailは、保護者がリンクされているあいだtrue、それ以外はfalseです。分岐に使うべきはこちらです。kuidは、セッションが紐づいている子どもプロファイルを識別します。
直近の招待はどうなったか
保存しているchallengeIdを指定してGET /challenge/get-statusを呼び出します。
| ステータス | 意味 | 推奨するUI |
|---|---|---|
PENDING | 招待は作成されメールも送信済みだが、保護者はまだ開いていない | parentEmailを示しつつ、招待を保留中として表示する |
IN_PROGRESS | 保護者がリンクを開いてフローを開始した | parentEmailを示しつつ、招待を保留中として表示する |
PASS | 保護者が完了し、セッションがリンクされた | 保護者が接続済みであることを表示する |
FAIL | 招待がキャンセルされた、または終了した | 接続された保護者はいないと表示し、別の招待を促す |
組み合わせて使う
プレイヤーのプロフィールを描画するときは次のようにします。
/session/getを呼び出します。hasApproverEmailがtrueなら保護者が接続済みであることを表示し、ステップ7のリンク解除の導線を提供します。- そうでなければ、直近の
challengeIdで/challenge/get-statusを呼び出します。PENDINGまたはIN_PROGRESS: 招待を保留中として表示し、キャンセルを提供します。PASSなのに/session/getではまだ保護者が見えない: 一時的な競合です。保留中として扱い、少し後に再確認します。FAIL、またはchallengeIdを保存していない: 招待の導線を表示します。
ステップ6: 保留中の招待をキャンセルする
保護者が本人確認の途中であっても、プレイヤーが招待を取り消したい場合はPOST /challenge/cancel-inviteを呼び出します。
POST /challenge/cancel-invite
{
"challengeId": "ae6d4729-af32-42ea-8ef2-ff46c7664802"
}
{ "cancelled": true }
チャレンジはfailureReason: "cancelled-by-initiator"とともにFAILへ移り、status: FAILのChallenge.StateChangeが届きます。すでに本人確認ウィジェットを開いている保護者にはキャンセル済みの状態が表示されます。
すでにキャンセル済みの招待をキャンセルしても安全で、再びcancelled: trueが返ります。
| コード | 発生する状況 |
|---|---|
NOT_FOUND | そのプロダクトにチャレンジが存在しない |
INVALID_INPUT | Invalid challenge type。このエンドポイントでキャンセルできるのは保護者招待チャレンジだけ |
INVALID_INPUT | Invite already accepted。キャンセルが届く前に保護者が完了した |
FEATURE_DISABLED | 組織でVPLが無効 |
FAILのあと、セッションはすぐに新しい招待を受け付けます。
ステップ7: リンク解除を処理する
どちらの側もいつでも関係を終わらせられます。保護者はFamily Connectから解除でき、あなたはプロダクト内でプレイヤーに解除の導線を提供できます。
リンク解除により、セッションは紐づけのない状態に戻ります。kuidと保護者リンクがクリアされ、保護者が設定したアローワンスとコントロールも取り除かれます。セッション自体はACTIVEのまま残り、プレイヤーの権限と送信済みデータも保持されます。プレイヤーは同じsessionIdのまま利用を続けます。
プロダクトからリンクを解除する
POST /session/unlink-parent
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"locale": "en"
}
{
"unlinked": true,
"unlinkedAt": "2026-04-20T18:42:11Z"
}
unlinkedは、この呼び出しまたは以前の呼び出しが保護者リンクを終わらせた場合にtrueになります。そもそも保護者がリンクされていなかった場合はfalseとなり、unlinkedAtは省略されます。localeは、リンクが終わったことを知らせるためにk-IDが保護者へ送る通知メールの言語を指定します。省略した場合、k-IDはその保護者をすでに把握していればその保護者自身の登録言語を使い、次にプロダクトの主要言語、最後に英語にフォールバックします。
この呼び出しはsessionIdに対して冪等です。リンクがすでに解除された後に再度呼び出しても、200と元のunlinkedAtが返り、再呼び出しの時刻にはなりません。
| コード | 発生する状況 |
|---|---|
NOT_FOUND | セッションが存在しない |
INVALID_INPUT | セッションの管轄区域がプロダクトに設定されていない |
FEATURE_DISABLED | Unlink is only available for VPL-linked sessions。セッションがVPLの経路にない、または組織でVPLが無効 |
Session.Unlinkウェブフック
k-IDは、どちらの側からであれリンクが終わるたびにSession.Unlinkを送信します。
{
"eventType": "Session.Unlink",
"data": {
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"productId": 12345,
"unlinkedBy": "player",
"unlinkedAt": "2026-04-20T18:42:11Z"
}
}
unlinkedByは、あなたのAPIを通じた解除ならplayer、保護者がFamily Connectから解除したならparentです。
受信したら、保護者が接続されている表示をやめてください。プレイヤーはいつでも新しい招待を送れます。
次のステップ
検証済み保護者リンクの実装ができたら、次のリソースでさらに理解を深めてください。
- 検証済み保護者リンク(VPL):このガイドの背景となる概念。リンクとゲートの違い、そしてVPLとVPCが相互に排他的である理由
- セッション:リンク、リンク解除、再リンクをまたいだ
sessionIdとkuidの挙動 Session.Unlink:どちらかの側がリンクを解除したことを知らせるウェブフック- ウェブフック:ウェブフックの購読、配信、署名検証の完全なガイド
- ローンチ前チェックリスト:本番公開前に確認すべき要件