コンテンツへスキップ

Webhook

クラウドフォンやクラウドブラウザーの操作が最終結果に達すると、MoreLogin が自社の HTTPS エンドポイントへ JSON イベントを POST するため、結果をポーリングする必要はありません。コールバック URL はチームごとに 1 つだけ保存され、Local API と Open API は同じレコードに書き込みます。

コールバック URL を設定する

どちらの入口でも同じ操作を提供しています。Open API:

curl -X POST "https://api.morelogin.com/webhook/config" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "callbackUrl": "https://example.com/morelogin/webhook",
    "enabled": true
  }'

Local API:

curl -X POST "http://127.0.0.1:40000/api/webhook/config" \
  -H "Content-Type: application/json" \
  -d '{
    "callbackUrl": "https://example.com/morelogin/webhook",
    "enabled": true
  }'

Local API のこのルートはデスクトップクライアントが提供するため、MoreLogin クライアント v2.66.0 以降が必要です。Open API の入口はクライアントに依存しません。

teamId はリクエストから読み取りません。各呼び出しはサーバー側コンテキストのチームを設定するため、他チームのイベントを自分のエンドポイントへ向けることはできません。

URL は HTTPS で、1〜1024 文字、ホスト名があり、ユーザー情報とフラグメントを含まず、ポートが正しい必要があります。解決先のすべてのアドレスが公開経路である必要があり、localhost、プライベート、リンクローカル、CGNAT、クラウドメタデータ、プロトコル予約、ドキュメント用、6to4 などの範囲は 41001 で拒否されます。配信が接続を開く時点でも同じ検査を行うため、後からプライベート範囲に解決されるホスト名は、その配信が失敗するだけで、あなたのネットワークには到達しません。

保存はチーム単位の upsert なので、同じ本文を 2 回送っても影響はありません。

配信を停止する

enabled: false は保存済みの URL を残したまま、新しいイベントの作成を停止します。すでにキューにあるイベントは 1 件ずつキャンセルされますが、キャンセルされるのは各イベントが次に承認される時点で、かつ設定がまだ停止中の場合だけです。そのためすぐに再有効化すれば、キュー内のイベントは破棄されずそのまま配信されます。

配信の中身

各配信は次のヘッダーを持つ POST です:

ヘッダー値
Content-Typeapplication/json
User-AgentMoreLogin-Webhook/1.0
X-Webhook-Event-Id本文の eventId と同じ
X-Webhook-Event-Type本文の eventType と同じ

2 つの X-Webhook-* ヘッダーは意図的に本文のフィールドと重複させています。これによりルーターやキューは JSON を解析せずに振り分けられます。

{
  "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
  "eventType": "cloud_phone.power_off",
  "eventTime": "1787241600000",
  "data": {
    "teamId": "10001",
    "cloudPhoneId": "20001",
    "reason": "MONEY_SAVING"
  },
  "result": {
    "success": true,
    "code": "0",
    "message": null
  }
}
フィールド説明
eventId一意のイベント ID。同じイベントの再送や内部リプレイでも再利用されるため、これが冪等キーになります
eventType安定したイベント名。値は下の表を参照
eventTime最終結果が発生した時刻。Unix エポックのミリ秒で、文字列として送信
data.teamIdこのリソースを所有するチーム。文字列として送信
data.cloudPhoneIdこのイベントの対象となるクラウドフォン。文字列として送信
data.cloudBrowserIdこのイベントの対象となるクラウドブラウザーのプロファイル。文字列として送信
data.runIdこのイベントの対象となるクラウドブラウザーの実行インスタンス
data.reasoncloud_phone.power_off と cloud_browser.stop のみに付きます
result.successこの操作が最終的に成功したかどうか
result.code成功時は 0。それ以外は言語に依存しない安定したビジネスエラーコード
result.message成功時は null。それ以外はチームの言語による説明で、無い場合は en-US にフォールバック

数値の識別子と eventTime はすべて JSON 文字列として届きます。API の他の部分と同じ扱いです(共通レスポンス形式 を参照)。数値ではなく文字列として解析してください。そうしないと 64 ビット ID の精度が失われます。

イベント

eventType報告される最終結果
cloud_phone.power_on起動の成功または失敗
cloud_phone.power_off停止の成功。停止が失敗した場合はイベントは発生しません
cloud_phone.restart再起動の成功または失敗
cloud_phone.resetリセットの成功または失敗
cloud_phone.new_machineワンクリック新規端末化の成功または失敗
cloud_browser.startクラウドブラウザーの起動の成功または失敗
cloud_browser.stopクラウドブラウザーの停止試行ごとの成功・失敗

クラウドフォンのイベントは teamId と cloudPhoneId を含みます。クラウドブラウザーのイベントは teamId、cloudBrowserId、runId を含みます。

起動、再起動、リセット、ワンクリック新規端末化が success: true を報告するのは、デバイスサービスのコールバックが成功し、ローカル同期がコミットされた後だけです。起動時の課金失敗、または非同期のプロキシ検査が失敗して後処理まで完了した場合は起動失敗を報告し、別途停止イベントは発生しません。プリセットアプリのインストールや期限切れファイルの削除など後回しにされた処理は、この結果を変更しません。

停止操作が起動を中断した場合、その試行では起動イベントは発生しません。その後に停止が成功すれば、独立した cloud_phone.power_off が発生します。

停止理由

cloud_phone.power_off は data.reason を追加します:

値意味
NORMAL通常の停止
MONEY_SAVING節約モード
OTHER未払い、期限切れ、保守、その他

cloud_browser.stop は data.reason を追加します:

値意味
NORMAL通常の終了
MONEY_SAVING節約モード
ENERGY_SAVING省電力モード
BROWSER_EXITEDブラウザーが予期せず終了した
OTHERその他

内部のアーカイブ失敗は result のみに影響し、停止開始時に確定した reason を上書きすることはありません。

配信、リトライ、順序

2xx はすべて配信成功として扱います。それ以外のステータス、接続タイムアウト、読み取りタイムアウト、ネットワークエラーはすべて失敗です。接続タイムアウトは 5 秒、読み取りタイムアウトは 30 秒です。

配信が失敗した場合、最大 6 回リトライし、間隔は 10 秒、30 秒、60 秒、3 分、10 分、30 分です。つまり 1 つのイベントで最大 7 回のリクエストになります。6 回目のリトライが失敗すると、そのイベントは自動リトライを停止します。

同じクラウドフォン、または同じクラウドブラウザーのイベントは、作成順に 1 件ずつ配信されます。異なるリソースは並行して配信されるため、それらの間の順序は前提にしないでください。

1 つのイベントのリトライは、常に同じ eventId、eventTime、本文を再利用します。ネットワークや復旧の例外的な状況では、これらの値が変わらないまま同じイベントが複数回配信されることがあるため、eventId で重複排除してください。

クラウドブラウザーの停止では、1 回の停止試行がちょうど 1 つのイベントを生成します。その後の手動リトライ、手動の強制解放、システムによる強制解放はいずれも新しい操作であり、新しい eventId が割り当てられます。2 回の試行が 1 つのイベントにまとめられることはありません。

クラウドフォンの操作は、デバイスサービスのタスク ID、traceId、または安定した業務時刻で識別します。いずれも存在しない場合、サービスは UUID を生成し、現在の最終コールバックを新しい操作として扱うため、2 つの異なる操作が 1 つにまとまるのではなく、新しい eventId が発行されます。

受信側の実装

イベントを保存できたらすぐに 2xx を返し、実処理は非同期で行ってください。レスポンス本文は無視されます。処理が遅いと 30 秒の読み取り予算を使い切り、受信済みであってもそのイベントはリトライ待ちに回されます。

eventId で重複排除してください。重複は既に処理済みとして扱い、副作用を再実行しないようにします。

自分のエンドポイントに届いたからといって、本文を信頼できる入力として扱わないでください。本リリースではコールバックに署名しないため、URL を知った人は誰でも送信できます。推測しにくい URL を使い、コストの大きい処理を行う前に API で状態を確認してください。たとえばクラウドフォンなら POST /cloudphone/info、クラウドブラウザーの実行なら POST /cloudbrowser/page です。

result.code は同期 API と同じビジネスエラーコードを使うため、失敗は エラーコード で調べられます。result.message は人間向けの文字列で、文言も言語も変わる可能性があります。分岐は result.success と result.code で行い、result.message では決して行わないでください。

各イベントの機械可読な契約(スキーマとイベントごとの例を含む)は、共有リソースの仕様とともに Shared Resources Open API で公開されています。