sent-integration-starter について
sent-integration-starterは、Sent連携を構築する開発者向けスキルです。認証、冪等送信、Webhook検証、運用上の対策を段階的な実装手順とリリースチェックリストで扱います。
主な機能
- 01認証情報とクライアントのライフサイクル指針
- 02冪等送信のパターン
- 03Webhook署名検証の指針
- 04リトライとレート制限への対応
- 05ログ記録とリリースチェックリスト
活用シーン
- 01アプリケーションのSent API認証設計
- 02タイムアウト後の重複送信防止
- 03検証済みWebhookレシーバーの構築
- 04Sent連携のリリース準備
MCP 対応
Sent MCPサーバーはクライアント管理のOAuthを使用し、REST APIキー認証とは異なると説明しています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sentdm/ sent-plugin --skill sent-integration-starterインストール後、Claude Code で/sent-integration-starterを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/errors-and-limits.mdsdk-and-frameworks.mdscripts/preflight.py詳細
Sent Integration Starter
Sent のインテグレーションを、認証、冪等性のある送信、検証済みイベントの受信、堅牢化の 4 段階で立ち上げます。これらを混同しないでください。多くの壊れたインテグレーションは第 1 段階を通過しても、第 3 段階をスキップしています。
Stage 1: クライアントと認証情報
Sent v3 REST リクエストは、x-api-key ヘッダーで認証します。アプリケーションのプロキシは、独自の呼び出し元から Authorization: Bearer を受け付ける場合があり、Sent MCP サーバーはクライアント管理の OAuth を使用しますが、どちらも api.sent.dm に送信される REST ヘッダーは変わりません。組織キーでは、子プロファイルとして操作するために x-profile-id を追加できます。プロファイルスコープのキーでこのヘッダーを送信すると、403 が返されます。
| 言語 | パッケージ | クライアント |
|---|---|---|
| TypeScript | @sentdm/sentdm | new SentDm({ apiKey }) |
| Python | sentdm(sent_dm をインポート) | Sent(api_key=api_key) または AsyncSent(api_key=api_key) |
| Go | github.com/sentdm/sent-dm-go | sentdm.NewClient(option.WithAPIKey(apiKey)) |
| Java | dm.sent:sent-java | SentOkHttpClient.builder().apiKey(apiKey).build() |
| C# | Sentdm | new SentClient { ApiKey = apiKey } |
| PHP | sentdm/sent-dm-php | new SentDm\Client($apiKey) |
| Ruby | sentdm | Sentdm::Client.new(api_key: api_key) |
生成されたアプリケーションコードでは、アプリケーションの所有者から提供される空でない API キーを明示的に必須とし、SDK の認証情報オプションに渡してください。各 webhook id に対応する署名シークレットを解決し、受信側のヘルパーに渡してください。プラグインのインストーラーの環境変数、認証情報ストア、MCP トークンは決して調べないでください。プラグイン自体はクライアント管理の OAuth を通じて認証します。マルチテナントの本番環境の受信側には、webhook id をキーとするシークレットレジストリが必要です。
認証情報モデルに応じて、クライアントのライフサイクルを選択してください。サーバー管理のキーを 1 つ使う単一アカウントのサービスでは、長期間使用するクライアントとその接続プールを再利用してください。リクエストごとに呼び出し元またはプロファイルの認証情報を解決するマルチテナントのプロキシでは、そのリクエスト用にクライアントを構築して破棄し、テナントの認証情報が共有状態を通じて漏洩しないようにしてください。フレームワーク固有の設定、Ruby の messages.send_ という命名上の癖、エコシステムごとのバックグラウンド処理の選択については、SDK とフレームワークを参照してください。
設定は起動時に検証し、キーがない場合は最初の顧客への送信で認証エラーを表面化させるのではなく、すぐに失敗させてください。
Stage 2: 冪等性のある送信
{
"to": ["+14155551234"],
"template": {
"name": "order_confirmation",
"parameters": { "order_id": "12345" }
},
"sandbox": true
}
必須フィールドは to のみです。template または text を指定し、チャネルの自動選択に任せる場合は channel を省略してください。フォールバックを期待して複数の値を含む channel 配列を設定してはいけません。これはブロードキャストとなり、料金が倍増します。チャネルの決定は sent-routing-strategist に任せてください。
タイムアウト後の再試行で二重送信されないよう、独自のドメインオブジェクトから決定論的に導出した Idempotency-Key を、すべての POST、PUT、PATCH で送信してください(たとえば、注文 ID と通知タイプを組み合わせます)。キーは [A-Za-z0-9_-] で構成される 1~255 文字で、顧客ごとに 24 時間キャッシュされます。再送されたリクエストには、キャッシュされた本文と Idempotent-Replayed: true、X-Original-Request-Id が返されます。元のリクエストがまだ処理中に重複リクエストが届くと、最大 5 秒間待機した後、409 CONFLICT_001 で失敗します。503 SERVICE_001 は、冪等性ストアが利用できず、リクエストが意図的に実行されなかったことを意味します。
202 は受け付け済みを意味し、配信済みを意味するものではありません。返された message_id の値は、独自のテナント、プロファイル、論理送信の識別子とともに、直ちに永続化してください。Webhook イベントには Sent のメッセージ ID とアカウントデータが含まれますが、アプリケーションのテナント識別子は含まれません。
ステージ 3:検証済み Webhook 受信先
受信先のない連携では、配信の実態を把握できません。エンドポイントを登録したら、すべての配信を検証してください。{x-webhook-id}.{x-webhook-timestamp}.{raw_body} に対する HMAC-SHA256 を計算します。キーには、whsec_ を取り除いてから Base64 デコードしたシークレットを使い、定数時間で比較し、タイムスタンプが 300 秒を超えて前後している場合は拒否します。どの言語向けにも、検証機能を含む SDK はありません。
処理を行う前に 200 で応答し、送信イベントは {message_id}:{message_status}、受信イベントは message_id をキーに重複を排除します。配信に 10 回連続で失敗すると、エンドポイントは無効になります。詳しい仕組みは sent-webhook-engineer に任せてください。ここでは、検証済みで、速やかに応答し、重複を排除する受信先をローンチ要件とします。
ステージ 4:堅牢化
レスポンスの種類ごとの再試行ポリシー
| レスポンス | 再試行 | 方法 |
|---|---|---|
2xx | いいえ | 成功 |
400、422 VALIDATION_* | いいえ | リクエストを修正します |
401、403 AUTH_* | いいえ | ただちに停止します。認証に 10 回連続で失敗すると、段階的にロックアウト期間が延長されながら、認証情報がロックされます |
404 RESOURCE_* | いいえ | 参照先のオブジェクトが存在しません |
409 CONFLICT_001 | はい。一時停止後に 1 回 | 同時に発生した重複リクエストが処理中です |
429 | はい | Retry-After に従い、ジッターを加えたバックオフを行います |
5xx、503 SERVICE_001 | はい | 上限を設けた指数バックオフにジッターを加えます |
| タイムアウトでレスポンスなし | 根拠がある場合に限り安全に再試行できます | 同じ Idempotency-Key を再利用します。キーまたは受信者で信頼できる API 検索を行う方法がないため、キーがなければ再送を自動化しないでください |
標準のレート制限は、スライディングウィンドウで 1 分あたり 200 リクエストです。POST /v3/webhooks/{id}/rotate-secret と POST /v3/webhooks/{id}/test は 1 分あたり 10 リクエストに制限されています。レート制限ヘッダーが表示されるのは 429 のレスポンスのみです。そのため、ペース配分は測定するのではなく設計する必要があります。一括処理では 1 リクエストあたり最大 1,000 人の受信者を指定し、毎秒およそ 1 リクエストのペースで送信してください。
エラー処理
エラーは {success, data, error: {code, message, details, doc_url}, meta: {request_id, timestamp, version}} の形式で届きます。メッセージのテキストや個別のコードではなく、error.code のプレフィックス群(AUTH_、VALIDATION_、RESOURCE_、BUSINESS_、CONFLICT_、SERVICE_、INTERNAL_)に基づいて処理を分岐してください。再試行の分類を含む全 46 コードの一覧は、references/errors-and-limits.md にあります。
直感に反するコードが 2 つあります。BUSINESS_003 と BUSINESS_004 はリクエストレベルのエラーとして記載されていますが、POST /v3/messages ではリクエストが 202 で受け付けられ、該当するメッセージは最終的に BLOCKED および FILTERED になります。そのため、残高不足でも送信呼び出しは失敗しません。
可観測性
成功・失敗を問わず、すべてのレスポンスで meta.request_id をログに記録してください。これはサポートへの問い合わせ時に使う相関 ID です。論理的な送信と、返された message_id の対応関係を記録し、ルート変更の経緯を監査できるよう、イベント履歴を追記専用で保存してください。API キー、Webhook 署名シークレット、payment_details、または保持ポリシーで許可される範囲を超える受信者のメッセージ本文を、決してログに記録しないでください。
リリースチェックリスト
- 認証情報はアプリケーションが管理する設定から明示的に渡され、コミットされていません。また、環境ごとに個別のキーが用意されています。
- クライアントのライフサイクルは認証情報のスコープに合っています。サーバー管理のキーが1つの場合は共有し、テナントが認証情報を指定する場合はリクエストごとに作成します。
- すべての変更を伴う呼び出しに、決定論的に生成した
Idempotency-Keyを指定します。 - エラーの種類に応じて、再試行可能なものと終端エラーを区別する再試行ポリシーを設定します。
- 一括処理では毎分200リクエストを超えないように調整し、1バッチあたりの宛先を最大1,000件にします。
- Webhook の受信側で署名とタイムスタンプを検証し、速やかに
200を返して重複を排除します。 - 実際の失敗時には受信側が non-2xx を返し、Sent が再試行できるようにします。
-
message_idとテナントの対応付けを送信前に永続化します。 -
request_idをログに記録し、シークレットやカード情報は記録しません。 - サンドボックスのスモークテストに合格した後、実際の送信が
DELIVEREDに到達します。 - アラートで Webhook の
consecutive_failures、429の発生数、フィルタリング率またはブロック率を監視します。
検証
認証情報もネットワークも不要なローカルの事前チェックを実行します。
python3 scripts/preflight.py --self-test
次に、"sandbox": true を指定して実際の処理経路を検証します。この設定では認証と検証は行われますが、処理は実行されません。最後に、受信側で DELIVERED を確認しながら、ライブ送信を1件行います。
境界
受信側の詳細については sent-webhook-engineer、チャネルの選択については sent-routing-strategist、確認済みの単発送信については sent-messaging、受信メッセージと同意については sent-two-way-messaging、マルチテナントのプロビジョニングについては sent-profile-provisioning、別の CPaaS プロバイダーからの置き換えについては migrate-to-sent を使用してください。