tiun-sdk について
tiun-sdkは、tiunのJavaScript SDKやReact Native SDKの統合・デバッグを支援するエージェント向けスキルです。サブスクリプション、一回限りの購入、時間制アクセスを扱い、プラットフォーム別の手順と安全な認可方法を案内します。
主な機能
- 01サブスクリプションと一回購入の設定案内
- 02時間制アクセスフローの説明
- 03WebとReact Native SDKの区別
- 04MCPの検出とインストールの案内
- 05バックエンドでのトークン検証案内
活用シーン
- 01Webアプリにサブスクリプション決済を統合
- 02一回購入後のコンテンツアクセス制御
- 03有料コンテンツに時間制アクセスを追加
- 04SDK設定や環境の不一致を調査
MCP 対応
このスキルはtiunのMCPを検出し、未導入の場合はインストールを提案するようエージェントに指示します。接続・認証済みなら、MCPでプロバイダーと商品を列挙し、統合方法の選択に利用できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tiun-app/ skills --skill tiun-sdkインストール後、Claude Code で/tiun-sdkを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-reference.mddiscovery.mdevents.mdframeworks.mdinstallation.mdmcp.mdone-time.mdoverview.mdreact-native.mdserver-verification.mdsubscriptions.mdtime-based.mdtroubleshooting.md詳細
tiun SDK スキル
ユーザーが @tiun/sdk または @tiun/react-native-sdk を使用するコードを統合、拡張、デバッグするときは、このスキルを使用してください。信頼できる上流ドキュメント:https://docs.tiun.io/llms-full.txt。
tiun とは
認証、決済、エンタイトルメントを単一の JS SDK で提供する商用バックエンドプラットフォームです。tiun シングルトンは 3 つのフローに対応しており、インテグレーターの意図に応じて選択します(「ステップ 0 — コードを書く前の要件確認」を参照)。
- サブスクリプション — 永続的なユーザーアカウント(OTP ログイン)、定期請求、
user.productAccess[]の製品ごとのエンタイトルメント。エントリーポイント:tiun.checkout({ productId })。references/subscriptions.md を参照してください。 - 一回限りの購入 — サブスクリプションと同じアカウントおよびエントリーポイントを使用しますが、固定料金が 1 回発生し、エンタイトルメントは永続的です。期間、トライアル、更新、有効期限はありません。エントリーポイント:
tiun.checkout({ productId })。references/one-time.md を参照してください。 - 時間ベース — セッションごとの匿名アクセス(アカウント不要)で、有料コンテンツの利用時間に応じて課金されます。エントリーポイント:
tiun.start()+paywallShow/paywallHideイベント。references/time-based.md を参照してください。
インストール:npm install @tiun/sdk。初期化:アプリ起動時に tiun.init({ snippetId, language: 'en' }) を呼び出します(冪等)。
tiun はライブ環境とサンドボックス環境を、独立した 2 つの並列環境として実行します。SDK の sandbox フラグでどちらを使用するか選択します。references/installation.md を参照してください。
React Native には別の SDK を使用します。 @tiun/react-native-sdk は <TiunProvider> と useTiun() / useTiunEvent() を使用し、host で環境を選択します(sandbox フラグはありません)。returnUrl ディープリンクが必要で、サブスクリプションと一回限りの購入のみを対象としています。詳細はすべて references/react-native.md に記載されています。以下の tiun.* コード、最小動作例、フレームワークごとの設定はウェブ専用です。React Native アプリでは決して生成しないでください。
ステップ 0 — コードを書く前の確認
まずプラットフォームを確認します。 何か質問する前にプロジェクトを確認してください。package.json に react-native 依存関係がある場合(または ios/ と android/ フォルダーがある場合)は React Native です。この確認と並行して references/react-native.md に従ってください。それ以外は Web SDK です。React Native では時間ベースは利用できません。ユーザーから希望された場合は、0b でその旨を伝えてください。
連携コードを書く前に、4 つの項目を確認してください。ユーザーがすでに伝えている項目は質問しないでください。プロンプトに必要な情報がすべて含まれている場合(「サンドボックスで、商品 p-test-pro を使ってサブスクリプションを設定し、/watch/* を制限対象にする」など)は、確認を省略してください。
クライアントが対応している場合は、構造化された質問プリミティブ(例:AskQuestion)を使ってください。対応していない場合は、チャット内で直接質問してください。
0a. MCP を検出し、見つからない場合はインストールを提案します。 クライアントごとのインストール手順と検出方法については、references/mcp.md を参照してください。状態は 3 つあります。
- MCP があり、認証済み → 0c でプロバイダーと商品を列挙するために使います。
- MCP はあるが、未認証 → 認証を一度だけ促します。拒否された場合は手動モードで続行します。
- MCP がない → インストールを提案します(1 文で価値を伝えます:「snippetId と productIds を直接取得して、コピー&ペーストによるミスを防ぎます」)。拒否された場合は手動モードで続行します。
0b. 連携モードを確認します。 サブスクリプション、買い切り、時間ベース、またはその組み合わせのどれですか?ユーザーの表現から各モードを判断する手がかりについては、references/discovery.md を参照してください。アカウントの在庫からモードを推測してはいけません。 現時点では商品タイプが 1 種類しかないプロバイダーでも、今後別のタイプを追加する予定かもしれません。
0c. 識別子を集めます。 質問内容は、モードと MCP の利用可否によって異なります。
- サブスクリプション、MCP あり → プロバイダーを一覧表示してユーザーに選んでもらいます。商品を一覧表示し、1 つまたは複数のティアを選んでもらいます。プロバイダーのサンドボックス/本番タグから環境を確認します。
- サブスクリプション、MCP なし →
snippetIdを尋ねます。商品を 1 つにするか複数のティアにするかを尋ねます。それぞれについて、productIdとラベルを尋ねます。サンドボックスか本番かを確認します(p-test-.../p-live-...のプレフィックスは有力な手がかりです)。 - 買い切り、MCP あり → プロバイダーを一覧表示してユーザーに選んでもらいます。商品を一覧表示し、ロック解除する商品を選んでもらいます。プロバイダーのサンドボックス/本番タグから環境を確認します。買い切り商品にはティアがないため、ティアについて尋ねないでください。
- 買い切り、MCP なし →
snippetIdを尋ねます。各商品について、productIdとラベルを尋ねます。サンドボックスか本番かを確認します(プレフィックスは有力な手がかりです)。 - 時間ベース、MCP あり → プロバイダーを一覧表示してユーザーに選んでもらいます。プロバイダータグから環境を確認します。
- 時間ベース、MCP なし →
snippetIdを尋ねます。サンドボックスか本番かを確認します。
MCP がある場合は、何も知らない状態で尋ねるのではなく、在庫情報に基づいて質問してください(「サンドボックスの時間ベース商品 p-test-xxx があります。これを連携しますか?それとも、先にサブスクリプション商品を設定しますか?」)。
0d. アクセス制限の対象を特定します。 ここを確認しないと、エージェントは対象のないボイラープレートを生成することになります。以下を尋ねてください。
- アクセスが必要なルート/コンポーネント/機能はどれですか?
- サインアウト中のユーザーには何を表示しますか?また、アプリ内の利用開始の流れはどのようなものですか?(オファーまたは料金ページ/アップグレード案内を見る前にサインインする、アカウント優先のアプリ/全画面ペイウォール/プレビュー+購読)。アプリのために設計された利用の流れを維持してください。
- 認証済みでもアクセス権がないユーザーには何を表示しますか?(通常は「アップグレード」という文言を使い、同じ UX にします)
- 無料プレビューはありますか?(ある場合、ユーザーが実際に希望しているのはサブスクリプションではなく時間ベースである可能性を示すことが多いため、0b にフィードバックしてください)
- 複数のティアがある場合、どのルート/機能をどのティアに割り当てますか?
タスクごとの参照先
| タスク | 参照先 |
|---|---|
| 検出、スコープ設定、MCP の検出、モード選択 | references/discovery.md |
| クライアントごとの MCP のインストール、検出、認証 | references/mcp.md |
| tiun の概要、対応プラットフォーム、製品モデル、ホスト型 UI の境界 | references/overview.md |
| インストール/初期化/設定/ホストごとの環境変数の注入 | references/installation.md |
| メソッドまたはプロパティの検索 | references/api-reference.md |
| イベント名とペイロード | references/events.md |
| サブスクリプションのゲーティング(アカウント+継続課金)、チェックアウトとログインの選択 | references/subscriptions.md |
| 1 回限りの購入のゲーティング(固定料金、永続アクセス) | references/one-time.md |
| 時間ベースのペイウォール(セッション単位、匿名、従量制) | references/time-based.md |
| 信頼できるバックエンド認証 | references/server-verification.md |
| フレームワークへの組み込み(すべてのスタック)+ライフサイクルマトリックス | references/frameworks.md |
| 「オーバーレイが表示されない」、SSR エラー、サンドボックスの不一致、オーバーレイのインジェクションの不具合 | references/troubleshooting.md |
React Native:インストール、リターン用ディープリンク、TiunProvider、フック、host、デバイスでのテスト | references/react-native.md |
重要なルール
tiun.init({ snippetId, language })は起動の早い段階でクライアント上で実行します。Next.js/Nuxt では、クライアント専用のコンポーネント/プラグインでラップしてください。サーバー上では絶対に呼び出さないでください。initは冪等です。再度呼び出すと再初期化ではなく設定がマージされるため、isInitializedガードは不要です。snippetIdは秘密情報ではありません。環境を識別するものです。NEXT_PUBLIC_*/publicランタイム設定を使用してください。- チェックアウトに基づくゲーティング(サブスクリプションおよび一度限りの購入)では、単発の
tiun.user読み取りではなく、userChangeを信頼できる情報源として使用してください。権利はセッション中に変更されます。Web SDK のペイロードには、変更のきっかけを確認する必要がある場合に備えて、event: 'init' | 'login' | 'checkout' | 'logout' | 'update'が含まれます。React Native のペイロードにはeventフィールドがありません。その場合は、別個のlogin/logoutイベントを使用してください。 - 認可でクライアントを決して信頼しないでください。保護されたサーバーリソースには、
tiun.getUserVerificationToken()が返す JWT(有効期間は5分)をバックエンドに送信し、バックエンドでX-TIUN-API-KEYを指定してPOST /live_api/s2s/v1/users/verificationを呼び出し、検証してください。時間ベースの場合は、paywallHideのsessionIdをPATCH /live_api/s2s/v1/sessions/{sessionId}/statusで使用してください。references/server-verification.mdを参照してください。 - ホスト型 UI はブラックボックスです。再実装したり、変更したりしないでください。tiun はチェックアウト、ログイン、接続オーバーレイをシャドウ DOM に描画します。
tiun.checkout({ productId })、tiun.login()、またはtiun.start()で開き、それ以上の操作はしないでください。ノードの検索、追加、監視のためにshadowRootの内部にアクセスしてはいけません。テキスト、ツールチップ、バッジ、バナーを挿入してはいけません。CSS(ホストセレクター、::part、::slotted、!importantによる上書き)で対象にしてはいけません。位置を変えたり、ラップしたりしてはいけません。入力欄の値を読み取ってはいけません。内部構造にはバージョン管理がなく、予告なく変更されます。また、決済フロー内にあるため、挿入したコードが気付かれないまま失敗し、チェックアウトも停止させるおそれがあります。サポートされている設定箇所はinit()の設定(language、tone)とダッシュボードのみです。顧客が追加の説明文を必要とする場合は、オーバーレイを開く前に、トリガーの横にある顧客自身のページへ配置してください。オーバーレイの中には配置しないでください。設定やダッシュボードで公開されていない内容は、クライアント側で修正せず、[email protected] に問い合わせてください。references/overview.md を参照してください。 readyより前に呼び出されたメソッドは、キューに入るか何も行わない場合があります。checkout/login/start/setContent/logoutなどのメソッドは、すでに内部でensureInitialized()とawait this.waitForReady()を呼び出すため、ラップする必要はありません。- コンポーネントのアンマウント時には、
tiun.on(...)が返す登録解除ハンドラーを呼び出して、古いリスナーが残らないようにしてください。サブツリー全体を破棄する場合は、tiun.destroy()を呼び出してください。 - 本番環境とサンドボックスは、それぞれ独立した並行環境です。それぞれに固有のスニペット ID、商品、商品 ID のプレフィックス(
p-live-...とp-test-...)、API キー、API ベース URL(https://api.tiun.liveとhttps://api-sandbox.tiun.live)があります。環境切り替え(Web ではsandboxフラグ、React Native ではhost)は、ダッシュボードの表示環境および商品 ID のプレフィックスと一致させる必要があります。一致しない場合、チェックアウトはエラーを表示せずに失敗します。localhostは本番環境ではブロックされ、サンドボックスではデフォルトで有効です。各環境には、それぞれ固有の Settings → Environment setup(Web 用の本番ドメイン、アプリ用のアプリスキーム)があります。 - 実行時に商品一覧を取得する API はありません。商品は tiun ダッシュボード(
my.tiun.business)で設定し、ハードコードされたproductId文字列で参照します。tiun.getProducts()のようなメソッドや REST エンドポイントを作らず、ユーザーをダッシュボードへ案内してください。 - Webhook はありません。tiun は webhook を送信しません。バックエンド連携では、
getUserVerificationToken()が返す JWT またはpaywallHideのsessionIdを使って状態を処理してください。Webhook エンドポイントやイベントペイロードを作らないでください。 - 上流のドキュメントに忠実に従ってください。すべてのコード例は https://docs.tiun.io に準拠する必要があります。上流ドキュメントに記載のないパターン(カスタム SSR 配線、複数環境の設定、他言語のバックエンド SDK など)については、コード例を創作せず、ユーザーを上流ドキュメントへ案内してください。
- アカウントの商品構成から連携モードを推測しないでください。必ずユーザーに確認してください(「Step 0」を参照)。MCP が報告するのは「存在するもの」であり、連携担当者が「構築したいもの」ではありません。
- 一度限りの商品 ID は
productAccessに入ると恒久的に残ります。チェックアウト時に追加され、その後は削除されません。event: 'update'でも削除されません。一度限りの商品に対して、有効期限、更新、キャンセル、トライアル、取り消しの処理を生成しないでください。発生し得ない状態に対する無効なコードです。更新とキャンセルはサブスクリプションにのみ適用されます。references/one-time.mdを参照してください。 isInitialized/waitForReadyガードを追加するために、SDK メソッドをラップしないでください。tiun.checkout、tiun.login、tiun.start、tiun.setContent、tiun.logoutは、どれも内部ですでに両方を実行します。これらのメソッドをラップするヘルパーは不要です。init()にbaseUrlを渡さないでください。これは内部専用のフィールドで、tiun のインフラストラクチャ用に予約されています。Web SDK では、本番以外の環境にsandbox: trueを使用してください。公開されている環境切り替え方法はこれだけで、SDK が対応する API ホストへ自動的にルーティングします。(React Native は例外です。sandboxフラグはなく、hostで環境を選択します。references/react-native.mdを参照してください。)languageは選択肢が固定された列挙型です:'en' | 'de' | 'fr'。大文字と小文字は区別されません。未対応の値を指定すると、コンソールに一度だけ警告が表示され、'en'にフォールバックします。他の値を生成しないでください。error.codeに基づいてアプリのロジックを分岐させないでください。これは文字列ですが、公開された列挙型はなく、コードは SDK のバージョン間で変更される可能性があります。ユーザーにはerr.messageを表示し、サポート用にerr.codeをログに記録してください。- ランタイム設定は、バンドラーが実際に読み込むファイルに記述してください。
.env.exampleはドキュメント用であり、評価されることはありません。Vite は.env/.env.localを読み込みます。Next.js は.env.localを読み込み、クライアントに公開する値にはNEXT_PUBLIC_*プレフィックスが必要です。Nuxt はnuxt.config.tsのruntimeConfig.publicを通じて読み込みます。ホストごとの表についてはreferences/installation.mdを参照してください。 - アカウントへのログインには認証、購入にはチェックアウトを使用してください。サインアップまたはサインイン →
tiun.login()、商品またはプランの購入 →tiun.checkout({ productId })、サインアウト →tiun.logout()。ラベルではなく、アクションの目的で選択してください。購入時に必要となる認証や既存顧客への対応はチェックアウトが処理するため、購入アクションでは別のログインを経由せず、直接チェックアウトを開きます。これは購入アクションで何を開くかについての説明であり、アプリの構成についてではありません。購入優先のユーザージャーニーとアカウント優先のユーザージャーニーは、どちらも有効です。references/subscriptions.mdの「Choosing checkout or login」を参照してください。 - React Native のチェックアウトでは、3か所すべてで同じスキームが必要です。ダッシュボードの Settings → Environment setup → App scheme(例:
myapp://)、ネイティブ登録(iOS のInfo.plistとAppDelegateのRCTLinkingManager転送、Android のインテントフィルターとandroid:launchMode="singleTask")、およびTiunConfigのreturnUrl(例:myapp://tiun/return)です。新しいスキームを作るのではなく、アプリで既存のスキームを再利用し、hostが指す環境のダッシュボードに登録するようユーザーに伝えてください。不一致があると、決済には成功してもチェックアウトから戻れなくなります。references/react-native.mdを参照してください。
最小限の動作例
3 つのプリミティブで、サポートされているすべての環境で動作します。リアクティブなプリミティブ(state hook、ref、signal、store、DOM の更新)を、ご使用のスタックに合わせて調整してください。
import { tiun } from '@tiun/sdk';
tiun.init({ snippetId: 'YOUR_SNIPPET_ID', language: 'en' });
const off = tiun.on('userChange', ({ event, isAuthenticated, user }) => {
// push into your framework's reactive primitive
});
document.querySelector('#buy').onclick =
() => tiun.checkout({ productId: 'p-live-pro' });
// off(); tiun.destroy();
各モードの詳細な手順については、references/subscriptions.md、references/one-time.md、[references/time-based.md)を参照してください。フレームワークごとの調整については、references/frameworks.mdを参照してください。
判断の手がかり
- ユーザーが「サブスクリプション」「定期支払い」「会員」「有料アカウント」「商品とプラン」と言っている → サブスクリプションフロー。subscriptions.md に誘導します。
- ユーザーが「一度だけ購入」「一度だけ支払う」「買い切り」「生涯」「生涯利用権」「単発決済」「永久にロック解除」「定額料金」「永久ライセンス」「サブスクリプションなし」と言っている → 買い切りフロー。one-time.md に誘導します。
- ユーザーが「記事のペイウォール」「動画を見てから支払う」「セッション」「アカウント不要」「寄付の案内」「最初の N 秒は無料」と言っている → 時間ベースのフロー。time-based.md に誘導します。
- ユーザーが「ペイウォールで保護された動画」「プレミアムコンテンツ」と言っている(曖昧な場合) → どのモードか確認します。推測しないでください。
- ユーザーが「エージェントに tiun を統合させるには?」「AI コーディングエージェントで設定するには?」と聞いている → docs.tiun.ioの上流のエージェント統合ガイドと、
references/mcp.mdのnpx skills add tiun-app/skillsクイックスタートを案内します。 - ユーザーが「商品を一覧表示するには?」「すべての商品を取得するには?」と聞いている → 商品は
my.tiun.businessのダッシュボードで設定します。実行時の商品一覧 API はありません。(MCP はセットアップ用にエージェントへ商品情報を公開しますが、これは実行時の SDK 機能ではありません。) - ユーザーが「バックエンドで検証」「API を保護」「クライアントを信頼する」と言っている → サーバー検証を案内します(
X-TIUN-API-KEYヘッダー、環境ごとのベース URL)。 - ユーザーが sandbox、
localhost、「ローカルで動作しない理由」と言っている →sandbox: true、sandbox のスニペット ID、p-test-...の商品 ID を確認します(localhostではライブモードは完全にブロックされます)。 - ユーザーがオーバーレイのスタイル変更、フィールドのラベル変更、チェックアウトやログイン内へのヘルプテキスト/注記/ツールチップの追加を希望している → サポートされていません。オーバーレイの内部には手を加えないでください(ルール 5)。トリガーの隣にある独自のページへ文言を配置し、ブランディングの要望は [email protected] に案内します。
- ユーザーが購入、サインイン、サインアウトのアクションを組み込んでいる → 目的に応じて使い分けます。購入では
tiun.checkout({ productId })を開き、アカウントへのアクセスではtiun.login()を開き、サインアウトではtiun.logout()を呼び出します。アプリに既存のユーザーフローを維持してください(ルール 19)。 - 「オーバーレイが表示されない」「ready になる前にメソッドが呼び出された」などのエラー → トラブルシューティングを案内します。
- プロジェクトが React Native、またはユーザーが
@tiun/react-native-sdk、TiunProvider、useTiun、「iOS/Android アプリ」「ディープリンク」「returnUrl」「チェックアウト後にアプリへ戻らない」と言っている → references/react-native.mdを参照します。frameworks.md の WebView セクションや@tiun/sdkではありません。 - ユーザーが React Native アプリで時間ベースの課金を希望している → React Native SDK ではサポートされていません。その旨を伝え、[email protected] に案内します。