2つのエンドポイント、往復1回
AIアシスタントがMCP経由で呼び出しても、外部クライアントがHTTPSで呼び出しても、ご自身のバックエンドが呼び出しても、ロジックは同じです。
send_otp
コードを生成し、有効期間と試行回数カウンターとともにハッシュを保存し、ペアリング済みのAndroid経由でSMSをプッシュします。
ユーザーが受信
ユーザーが端末でSMSを読み、認証フォームにコードを入力します。
verify_otp
最後に発行したコードと定数時間で比較します。verifiedと、失敗時には残り試行回数を返します。
POSTのみ、Bearer認証
GETは405を返します。Cookieは無視されます。APIキーがURLや履歴に残ることはありません。
送信エンドポイント
POST https://app.sms8.io/ajax/otp-send.php
- phone 必須、E.164形式
- length 4〜8桁、デフォルト6
- expires_in 60〜900秒、デフォルト300
- max_attempts 1〜10、デフォルト5
- template
{code}プレースホルダーを含むテキスト - option / devices / useRandomDevice デバイス選択
検証エンドポイント
POST https://app.sms8.io/ajax/otp-verify.php
- phone 必須、E.164形式
- code ユーザーが入力したコード
レスポンス:
- 成功時
{verified: true} {verified: false, reason: "code_mismatch", attempts_left: 4}- その他の理由:
expired、not_found、max_attempts
コピペで使える呼び出し例
OTPを送信
curl -X POST https://app.sms8.io/ajax/otp-send.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+81901234567" # デフォルト値を上書き: # -d "length=6" -d "expires_in=300" # -d "max_attempts=5" # -d "template=認証コードは{code}です。まもなく有効期限が切れます。" # 送信デバイスまたはSIMを選択: # -d "option=0" --data-urlencode 'devices=["DEVICE_ID"]' # -d "option=1" # すべての端末にブロードキャスト # -d "option=2" # すべてのSIMにブロードキャスト # -d "useRandomDevice=1" # ランダムな送信元
コードを検証
curl -X POST https://app.sms8.io/ajax/otp-verify.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+81901234567" \ -d "code=123456" # 成功: {"verified": true} # 失敗: {"verified": false, "reason": "code_mismatch", "attempts_left": 4}
AIアシスタントから(MCP)
Claude Code、Cursor、Windsurfがmcp.sms8.ioに接続されているなら、こう尋ねてみてください: 「sms8 MCP経由でサインアップフローにSMS認証を追加してください」。アシスタントはデフォルト値でsend_otpとverify_otpを呼び出し、既存のサインアップやログインのルートを拡張します。
ダッシュボードから一度設定するだけ
フォールバック値を一度だけ設定すれば十分です。呼び出しでフィールドが空のときに自動的に適用されます。ハードコードされた上限はどんなときも変わりません。
コードの長さ
4〜8桁。デフォルトは6。覚えやすい短さと、ブルートフォースに耐える長さのバランスです。
有効期間
60〜900秒。デフォルトは300秒(5分)。リプレイを制限しつつ、ユーザーが入力する時間も確保します。
検証試行回数
コードがロックされる前の試行回数は1〜10。デフォルトは5。
再送クールダウン
同じ番号への2回の送信の間隔は30〜600秒。デフォルトは60秒。
SMSテンプレート
ブランドのトーンに合わせて文章を調整できます。唯一の制約は{code}プレースホルダーを残すことです。
顧客を守るハードコードされた上限
番号ごとに1日5OTP
最も厳しい上限です。アカウントから変更できません。キーが漏洩しても、どの番号も24時間スライディングウィンドウで5件を超えるコードを受信することはありません。
トランザクション制御
クールダウンと24時間上限はSELECT ... FOR UPDATEで処理されます。並列の呼び出しが回避することはできません。
定数時間検証
verify_otpはhash_equalsを使用します。タイミングリークはありません。
POSTのみ、Cookieなし
両エンドポイントへのGETは405を返します。認証ではCookieは無視されます。画像タグ経由のCSRFはありません。
OTPごとの試行上限
デフォルトでコードあたり5回の失敗まで。その後コードはロックされ、新しいsend_otpが必要です。
汎用的なエラーメッセージ
内部例外はInternal errorを返します。スタックトレースがクライアントに漏れることはありません。
OTPに関するご質問
SMS8でOTPはどうやって送信しますか?
番号を指定してhttps://app.sms8.io/ajax/otp-send.phpにPOSTしてください。エンドポイントはAuthorization: Bearerヘッダーを受け付けます。オプションフィールド: length(4〜8)、expires_in(60〜900秒)、max_attempts(1〜10)、template、デバイスセレクター。
verify_otpはどう動きますか?
ユーザーが入力したコードと番号をhttps://app.sms8.io/ajax/otp-verify.phpにPOSTしてください。サーバーは最後のOTPと定数時間で比較し、verified: trueまたはverified: falseを返します。失敗時にはreasonとattempts_leftが提供されます。
不正利用防止の上限は何ですか?
同一番号には24時間スライディングウィンドウで最大5件のOTPまで送信できます。ハードコードされており変更不可、キーが漏洩しても受信者を保護します。
SMS8のOTPにA2P 10DLCは必要ですか?
いいえ。SMS8はOTPをペアリングされたAndroidとSIMから送信するため、A2P 10DLC登録は不要です。
アシスタント自身でOTPを追加できますか?
はい。Claude Code向けに同梱されているSkillが、いつsend_otpとverify_otpを呼び出すかをアシスタントに教えます。「/signupに認証を追加してください」のようなプロンプトで十分です。