金融・保険・与信業務でPDF書類(口座明細、給与明細、保険金請求書類など)を扱うSpring Bootサービスを運用しているなら、外部API依存が1つ増えることの重みを見過ごせません。今回扱うのは、外部の検証APIを使ってPDFの構造的な改ざんを検知する仕組みと、それをSREの観点から安全に組み込む方法です。実装コードの紹介というより、可用性・SLO・障害対応という切り口で読み解きます。
この仕組みが対象にしているのは、本人確認(KYC、Know Your Customerの略で申込者が実在の本人かを確認する手続き)が保証しない領域です。申込者が本人であることと、その人がアップロードしたPDFが発行後に改変されていないことは、まったく別の問題になります。改ざん検知はこの構造的な差分を、ファイルを信頼する前の「入口」で潰す発想です。
APIの仕組みと呼び出しフロー
検知の流れは2段階に分かれます。まず POST /analyze にPDFのURLを送ると、非同期の検査IDが返ります。
次に GET /result/{id} でポーリングし、intact(改ざんなし)、modified(改ざんあり)、inconclusive(判定不能)のいずれかのステータスを受け取ります。
curl -X POST https://api.htpbe.tech/v1/analyze \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://api.htpbe.tech/v1/test/clean.pdf"}'この非同期パターン自体は目新しくありません。重要なのはSREとして見たときの意味です。同期APIなら失敗はHTTPステータスで即座に分かりますが、非同期ポーリングは「投げたのに結果が返ってこない」という半端な失敗モードを生みます。ここをどう設計するかが、この統合の実質的な難所になります。
実装例では、Spring 6.1以降で安定した RestClient(Spring公式の同期HTTPクライアント)を使い、レスポンスを型付きの record DTO(Javaのデータ専用クラス)にマッピングしています。リアクティブスタックなら WebClient を使う構成も示されており、既存のSpring WebFlux基盤にそのまま乗せられます。
SLO設計への影響を段階的に考える
まず確認すべきは、この外部APIの応答時間分布が自社のSLO(Service Level Objective、サービスが満たすべき品質目標)にどう影響するかです。
underwriting(与信審査)フローに同期的に組み込む場合、analyze → ポーリング → 判定という往復が発生します。この待ち時間がユーザー向けAPIのレイテンシSLOにそのまま乗ってしまう構成は避けたいところです。
たとえば「書類アップロードAPIのP99レイテンシを2秒以内」というSLOを既に持っているなら、改ざん検知の呼び出しはアップロード応答の外側、非同期ジョブとして分離するのが安全です。アップロードは201を返して先に完了させ、検知結果は別途Webhookやポーリングで受け取る設計にすれば、外部APIの遅延がクリティカルパスのSLOを侵食しません。
次に確認すべきはエラー分類です。実装例では、設定ミス(APIキー不正など)と一時的な障害(5xx、429のレート制限)を区別するための ResponseErrorHandler(Springのエラーハンドリング拡張ポイント)を用意しています。
この区別はSREにとって本質的です。設定ミスは即座にアラートを上げて人間が対応すべき障害ですが、5xxや429は自動リトライで吸収できる一時障害だからです。Spring Retryを使い、5xxと429のみバックオフ(再試行間隔を徐々に広げる制御)付きで再試行し、4xxの設定エラー系は即座に失敗させて運用者に通知する、という切り分けがそのまま障害対応Runbook(障害時の対応手順書)のたたき台になります。
関連する仕組みとの比較で位置づけを整理する
この検知APIは、OCR(光学文字認識)でもなければAI生成テキスト検出でもありません。PDF内部の構造、たとえば署名後の増分更新(incremental update、PDFに変更を追記していく仕組み)の有無や、Producer/Creatorメタデータの整合性を見ています。
レスポンス例にある has_incremental_updates や update_chain_length は、PDF仕様(ISO 32000)が持つ増分保存の仕組みを逆手に取った検知ロジックです。署名後にファイルへ追記があれば、それは編集の痕跡として残ります。
日本の開発現場でよく使われる文書検証手段と比べると、電子帳簿保存法対応で使われるタイムスタンプ検証やハッシュ突合は「改ざんされていないことの証明」を発行側が担保する仕組みです。一方この検知APIは受け取った側が事後的に構造を解析するアプローチで、発行元がタイムスタンプを付けていない書類にも適用できる点が異なります。
自前でPDF構造を解析する内製ライブラリを持つ選択肢もありますが、PDFパーサーの脆弱性対応やフォーマットの仕様変更への追従コストを考えると、SLAを持つ外部APIに切り出す判断は、認証基盤をAuth0やCognitoに任せる判断と近い性質があります。
今日確認できること
導入を検討するなら、まず自社のSpring Bootのバージョンを確認してください。RestClient は3.2以降で安定版のため、mvn dependency:tree や build.gradle のバージョン指定を見て3.2未満なら WebClient 経由の実装を検討することになります。
./mvnw dependency:tree | grep spring-boot-starter-web次に、外部API呼び出しを既存のオブザーバビリティ基盤(Micrometer、OpenTelemetryなど)に統合できるか確認します。analyze から result までの往復時間をヒストグラムメトリクスとして記録し、429や5xxの発生率を可視化しておけば、外部API側の劣化を自社のダッシュボードで先に検知できます。
最後に、Terraformなどのコード管理をしているなら、APIキーの管理場所を確認してください。@ConfigurationProperties で読み込む設定値をリポジトリに直書きせず、Vaultやクラウドのシークレットマネージャー経由で注入する構成になっているか、既存のシークレット管理ポリシーと照合しておくと安心です。
まとめ
外部の改ざん検知APIをSpring Bootに組み込む際は、コードの書き方以上に運用設計が問われます。
- 同期呼び出しにするか非同期化するかを、自社のレイテンシSLOと照らして先に決める
- 5xx/429の一時障害と4xxの設定エラーを区別し、リトライ対象を明確に分ける
has_incremental_updatesなどのレスポンス項目が何を検知しているかを理解し、KYCとの役割分担を混同しない- APIキー管理と呼び出しメトリクスを既存のシークレット管理・オブザーバビリティ基盤に接続する
まずは curl で /analyze と /result を叩き、実際のレスポンス時間とエラーコードの挙動を確認するところから始めてみてください。