OCR APIとWebhookで買掛金管理の自動化パイプラインを構築する
信頼性の高い買掛金管理の自動化パイプラインを構築する方法を解説します。非同期OCR APIで請求書をアップロードし、セキュアなWebhook経由で構造化データを受け取るフローを学びましょう。
請求書の処理は、多くの企業でボトルネックとなりがちな業務です。手作業によるデータ入力は時間がかかり、ミスも起こりやすいものです。OCR APIを導入しても、処理完了をポーリング(定期的な問い合わせ)で確認するシステムは非効率的です。システムの複雑さが増し、遅延や不要なトラフィックの原因にもなります。「処理はまだ終わらないか?」と常に確認し続けるような運用は、本当の意味での自動化とは言えません。理想的な買掛金管理ワークフローは、データが準備できた瞬間に即座に応答する、イベント駆動型であるべきです。

これこそが、space-ocrが採用する非同期処理の基本思想です。リクエストを送信して接続を維持し続ける代わりに、請求書を一括でアップロードすれば、すぐに他の作業に戻ることができます。APIは、ファイルが正常に受信されたことを示すジョブIDのリストを即座に返します。その後、当社のエンジンが各画像を処理します。請求書の読み取りが成功すると、アプリケーションのエンドポイントに直接通知が送信されます。この通知はWebhook、つまり構造化データを含んだシンプルなHTTP POSTリクエストによって行われます。
フローは非常にシンプルです。まず、請求書の画像をPOST /uploadに一度だけリクエストします。レスポンスとして、処理待ちジョブの配列が返ってきます。その後、あなたのサーバーはWebhook経由でocr.completedイベントを受信します。このイベントのペイロードには、「弥生サンブル」のような取引先名から、各明細項目のページ上の座標に至るまで、完全な抽出結果が含まれています。また、信頼性を高めるために、すべてのアップロードにIdempotency-Keyヘッダーを含めることができます。ネットワークエラーでリクエストを再試行する必要がある場合でも、同じキーを送信すれば、処理ジョブが重複して作成されることはありません。
const express = require('express');
const crypto = require('crypto');
// Middleware to get the raw body for signature verification
const rawBodySaver = (req, res, buf, encoding) => {
if (buf && buf.length) {
req.rawBody = buf.toString(encoding || 'utf8');
}
};
const app = express({ verify: rawBodySaver });
const webhookSecret = process.env.SPACE_OCR_WEBHOOK_SECRET;
app.post('/webhook', (req, res) => {
const signature = req.get('X-Spaceocr-Signature');
if (!signature) {
return res.status(400).send('Missing signature');
}
const hmac = crypto.createHmac('sha256', webhookSecret);
const digest = Buffer.from(hmac.update(req.rawBody).digest('hex'), 'hex');
const receivedSignature = Buffer.from(signature, 'hex');
if (!crypto.timingSafeEqual(digest, receivedSignature)) {
return res.status(400).send('Invalid signature');
}
// Signature is valid, now process the event
const event = JSON.parse(req.rawBody);
switch (event.event) {
case 'ocr.completed':
const { result } = event.data;
console.log(`OCR successful for ${result.name}:`, result.values);
// TODO: Add structured data to your accounting system
break;
case 'ocr.failed':
const { error } = event.data;
console.error(`OCR failed for ${event.data.name}:`, error.message);
break;
case 'webhook.test':
console.log('Webhook test successful!');
break;
default:
console.log(`Unhandled event type: ${event.event}`);
}
res.status(200).send({ received: true });
});
app.listen(3000, () => console.log('Webhook receiver listening on port 3000'));space-ocrはどのようにしてページ上のデータを特定するのでしょうか?まず、基盤となる言語モデルが、抽出したテキストとその位置を示す可能性のあるトークンヒントを返します。次に、当社のエンジンが重要な検証ステップを実行します。抽出された値を、ページ上で実際に検出されたOCRシンボルと一文字ずつ照合するのです。このプロセスにより、0.0から1.0までのmatch_ratioスコアが生成されます。スコアが0.85以上であれば、信頼性の高い一致と判断できます。最終的な座標は、元の画像のピクセルサイズに依存しない、0から1000の範囲で正規化されたバウンディングボックスとして返されます。
このような自動化は、誰もが気軽に利用できるべきだと考えています。API経由で処理される画像1枚あたりの料金は、一律で¥10です。すべてのアカウントには、毎月100スキャン分の無料枠が付与されます。さらに重要な点として、画像が読み取れずにOCRジョブが失敗した場合は、料金は一切かかりません。コストはデータ抽出の成功にのみ連動するため、リスクを抑えながら買掛金管理の自動化を始めることができます。
- 公開エンドポイントを用意するサーバーには公開URLが必要です。ローカルでの開発には、ngrokのようなサービスを利用してローカルサーバーをインターネットに公開します。
- Webhook URLを登録するspace-ocrのダッシュボード設定で、公開エンドポイントのURLを追加します。生成されたWebhookシークレットを安全な場所にコピーしてください。
- 署名検証を実装する提供されているコードサンプルを使用して、受信するすべてのリクエストの`X-Spaceocr-Signature`ヘッダーを検証し、リクエストが正当なものであることを確認します。
- ocr.completedイベントを処理する有効なイベントが届いたら、`data.result`オブジェクトをパースし、構造化された請求書データを会計システムやデータベースに渡します。
- 請求書を非同期でアップロードするファイルを添付して`POST /upload`リクエストを送信します。APIはOCRの完了を待たずに、即座にジョブの詳細を返します。
- イベントの受信を通知し、監視するエンドポイントは、受信を確認するために速やかに2xxステータスコードを返す必要があります。問題が発生した場合は、ダッシュボードの配信ログを監視してください。