---
type: how-to
title: サーバー側の連携
summary: 送信から caputchin-token を取り出し、リクエストを信頼する前に /siteverify で確認します。
---

ウィジェットはブラウザに一度きりのトークンを渡します。そのトークンは、サーバーが Caputchin で確認するまで何も証明しません。これは、目に見えるチャレンジを本物の保護に変えるステップで、HTTPS 呼び出し 1 回で済みます。

外向きのリクエストを出せるバックエンドと、そこで使えるサイトキーのシークレット（`cpt_sec_...`、決してブラウザにはないもの）が必要です。

## 1. トークンを読む

フォームがポストすると、ハンドラーはあなた自身のフィールドと並んで 1 つの追加フィールド `caputchin-token` を受け取ります。訪問者がチャレンジをクリアしたとき、ウィジェットがそれをフォームに注入しました。

## 2. /siteverify で確認する

トークンとシークレットを POST します。リクエストとレスポンスは reCAPTCHA の `siteverify` と同じ形なので、既存の連携はほとんど変更なく移植できます：

```http
POST https://verify.caputchin.com/v1/siteverify
Content-Type: application/json

{ "secret": "cpt_sec_...", "response": "<caputchin-token>" }
```

```js
// Node 18+
const verdict = await fetch("https://verify.caputchin.com/v1/siteverify", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    secret: process.env.CAPUTCHIN_SECRET,
    response: token,
  }),
}).then((r) => r.json());

if (!verdict.success) {
  // reject the submission
}
```

他の言語での同じ呼び出しは [バックエンド連携の例](/docs/integration-guides/backend-examples) にあります。

## 3. レスポンスを読む

```json
{
  "success": true,
  "error-codes": [],
  "platform": { "game_id": "caputchin/games/leaf-memory", "score": 847, "duration_ms": 4200 }
}
```

- **`success`** は分岐すべき唯一のものです。`true` は本物の訪問者がチャレンジをクリアしたことを意味します。リクエストを信頼してください。`false` はそれを捨てる意味です。
- **`error-codes`** は `success` が `false` のときに現れ、何が問題だったか（欠けた、期限切れの、またはすでに使われたトークンなど）を示します。
- **`platform`** はクライアントが申告するメタデータ（どのゲーム、スコア、所要時間）です。これは null になり得て、**セキュリティのシグナルではありません**。お望みなら分析のために記録してかまいませんが、スコアで信頼を判断しては決していけません。

## あなたを守るルール

- **一度きり。** トークンは一度だけ検証されます。同じものをもう一度送ると `success: false` が返るので、リプレイを自分で追跡する必要はありません。
- **短命。** トークンは発行から 10 分で期限切れになるので、遅延ジョブではなく、送信の処理中に検証してください。
- **シークレットはサーバーに留まる。** それは決してブラウザへは行かず、呼び出しを認証するものです。

## よくある間違い

- **クライアント側で検証する。** `pass` イベントとトークンの存在は UX のためだけです。すべての信頼の判断は、ここで、サーバー側で、あなたのシークレットを使って起きます。
- **`score` で判断する。** それはメタデータであり、信頼度の値ではありません。

## よくある質問

### トークンはどれくらい有効ですか？

発行から 10 分です。送信を処理している間に検証してください。遅延ジョブや、あとで動くかもしれないキューからではいけません。

### 同じトークンを 2 回検証できますか？

いいえ。トークンは一度きりです。同じものをもう一度送ると `success: false` が返るので、リプレイを自分で追跡する必要はありません。

### `score` や `game_id` を信頼すべきですか？

いいえ。`platform` ブロック（ゲーム、スコア、所要時間）はクライアントが申告するメタデータで、null になり得ます。`success` だけで分岐し、スコアで信頼を判断しては決していけません。

### これに SDK は必要ですか？

いいえ。チェックは `/v1/siteverify` への 1 回の HTTPS POST です。Node、Python、PHP、Go、Ruby、.NET、curl での同じ呼び出しは [バックエンド連携の例](/docs/integration-guides/backend-examples) にあります。

## あわせて読む

- あなたの言語でのこの呼び出しについては [バックエンド連携の例](/docs/integration-guides/backend-examples)。
- バックエンドを完全に省くには [ホスト型認証](/docs/hosted-verification/overview)。
