開発者向け

Formalini API

ドキュメントと抽出されたフィールドの読み取り、自社システムからのドキュメント登録、値の修正、変更時の署名付き Webhook 受信を行えます。以下のすべてのサンプルコードは curl、JavaScript、Python、PHP、C# で記載されています。

ベース URL

すべてのエンドポイントはこのベース URL の下にあります。JSON の送受信に対応しています。

https://api.formalini.com/api/public/v1

短縮アドレス api.formalini.com は現在利用可能です。上記に表示されているアドレスとなります。

認証

アプリ内の「連携」で API キーを作成し、各リクエストで Bearer トークンとして送信してください。キーは特定のワークスペースに紐づき、そのワークスペースのデータのみにアクセスできます。

  • documents.read — ドキュメントおよびフィールドの読み取り
  • documents.write — ドキュメントの作成およびフィールドの修正
  • workflows.run — オンデマンドでの Webhook へのイベント送信

各キーには1分あたりのリクエスト制限(デフォルト60件)が設定されています。レスポンスには X-RateLimit-Limit および X-RateLimit-Remaining が含まれ、上限を超えると Retry-After とともに 429 が返されます。

ドキュメント一覧の取得

GET /documents?limit=25&status=approved — documents.read

新しい順に取得されます。limit は 1〜100(デフォルト25)、status で queued、processing、review、approved、exported、failed ごとにフィルタリングできます。

curl -X GET "https://api.formalini.com/api/public/v1/documents?limit=25&status=approved" \
  -H "Authorization: Bearer pf_live_your_key"
{
  "documents": [
    {
      "id": "b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90",
      "name": "Job sheet 4821.jpg",
      "status": "approved",
      "average_confidence": 0.94,
      "source": "upload",
      "created_at": "2026-09-11T09:12:04.000Z",
      "fields": [
        { "name": "engineer", "value": "M. Byrne", "type": "text",
          "confidence": 0.97, "page": 1, "valid": true }
      ]
    }
  ]
}

修正された値は元の読み取り結果を上書きするため、常に value に指定された値をご使用ください。

単一ドキュメントの取得

GET /documents/{id} — documents.read

ドキュメントを、そのカテゴリー、取引先、金額、日付、およびすべてのフィールドとともに返します。

curl -X GET "https://api.formalini.com/api/public/v1/documents/b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90" \
  -H "Authorization: Bearer pf_live_your_key"

ファイルのアップロードとデータ取得

POST /documents/upload — documents.write

ページ画像を送信すると、同一レスポンス内で構造化データが返されます。ドキュメントは通常のスキャンと同様にワークベンチの受信トレイに表示され、1ページあたり1つの AI クレジットを消費し、完了時に Webhook を送信します。

  • file — ページ画像。複数ページのドキュメントの場合は、1ページにつき1回フィールドを繰り返します(最大25ページ)。
  • name — ドキュメント名(任意)。省略した場合はファイル名が使用されます。
  • template_id — テンプレート ID(任意)。指定すると、カスタム名が割り当てられたフィールドが返されます。
  • async — true に設定すると即座に 202 が返され、GET /documents/{id} をポーリングして結果を取得できます
curl -X POST "https://api.formalini.com/api/public/v1/documents/upload" \
  -H "Authorization: Bearer pf_live_your_key" \
  -F "file=@invoice-page-1.jpg" \
  -F "file=@invoice-page-2.jpg" \
  -F "name=Invoice 2026-0041"
{
  "document": {
    "id": "8c2a1f76-4d33-4a1e-8f10-72b9e5c4a118",
    "name": "Invoice 2026-0041",
    "status": "review",
    "average_confidence": 0.93,
    "vendor": "Northbridge Supplies",
    "amount": 1249.5,
    "currency": "EUR",
    "document_date": "2026-09-14",
    "pages": 2,
    "credits_spent": 2,
    "fields": [
      { "name": "invoice_number", "value": "2026-0041", "type": "string",
        "confidence": 0.98, "page": 1, "valid": true }
    ]
  }
}

JPEG、PNG、WebP、HEIC に対応しており、1ページあたり最大 100 MB です。1ページの読み取りには数秒かかるため、タイムアウトを長めに設定するか async=true を使用してください。402 はワークスペースのクレジット、ストレージ、または1日の利用上限が不足していることを意味し、レスポンスにその詳細が記載されます。

現在ここでは PDF に対応していません。各ページを JPEG または PNG にレンダリングし、複数の file フィールドとして送信してください。アプリ内での PDF アップロードはブラウザ上でページがレンダリングされるため、引き続き利用可能です。

ドキュメントの作成

POST /documents — documents.write

すでにデータが存在するドキュメントを登録します。name は必須、fields は任意で最大400件まで指定可能です。fields があるドキュメントは「確認中」に、ないものは「キュー」に入ります。

curl -X POST "https://api.formalini.com/api/public/v1/documents" \
  -H "Authorization: Bearer pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoice 2026-0041.pdf",
    "category": "invoice",
    "vendor": "Northbridge Supplies",
    "amount": 1249.5,
    "document_date": "2026-09-14",
    "fields": [
      {
        "name": "invoice_number",
        "value": "2026-0041",
        "type": "text",
        "confidence": 0.99,
        "page": 1
      },
      {
        "name": "total",
        "value": "1249.50",
        "type": "number",
        "confidence": 0.96,
        "page": 1
      }
    ]
  }'
{
  "document": {
    "id": "8c2a…",
    "name": "Invoice 2026-0041.pdf",
    "status": "review",
    "created_at": "2026-09-18T10:02:11.000Z",
    "fields": 2
  }
}

ドキュメントの更新

PATCH /documents/{id} — documents.write

ステータスの変更や、フィールド名指定での値修正を行います。ステータスを approved、exported、または review に設定すると、対応する Webhook もトリガーされます。

curl -X PATCH "https://api.formalini.com/api/public/v1/documents/b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90" \
  -H "Authorization: Bearer pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "approved",
    "fields": [
      {
        "name": "total",
        "value": "1249.50"
      }
    ]
  }'
{ "ok": true, "updated_fields": 1 }

Webhook のトリガー

POST /workflows/dispatch — workflows.run

購読しているすべてのアクティブな Webhook にイベントを送信し、オンデマンドで外部システムを起動できます。許可されているイベント:document.processed、document.needs_review、document.approved、document.exported。

curl -X POST "https://api.formalini.com/api/public/v1/workflows/dispatch" \
  -H "Authorization: Bearer pf_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "document.approved",
    "document_id": "b0f1c8d2-5a71-4c0e-9f2a-1d4b6e8c3a90",
    "payload": {
      "target": "erp"
    }
  }'
{ "ok": true, "event": "document.approved", "document_id": "b0f1…" }

Webhook

アプリ内で Webhook URL を追加し、受信したいイベントを選択します。各配信は JSON 本文と署名ヘッダー(Webhook シークレットで署名)を含む POST リクエストです。

POST https://your-app.example.com/hooks/formalini
Content-Type: application/json
X-Paperflow-Signature: sha256=<hex hmac of the raw body>

{ "event": "document.processed", "document_id": "b0f1…", "payload": { … } }

配信に失敗した場合は間隔を空けながら最大5回まで再試行され、アプリから手動で再送することも可能です。

配信を信頼する前に、未加工のリクエスト本文に対して署名を検証してください:

// Node.js
import crypto from "node:crypto";

function verify(rawBody, header, secret) {
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const got = (header || "").replace(/^sha256=/, "");
  return got.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}

# Python
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, (header or "").removeprefix("sha256="))

// PHP
$expected = hash_hmac('sha256', $rawBody, $secret);
$got = str_replace('sha256=', '', $_SERVER['HTTP_X_PAPERFLOW_SIGNATURE'] ?? '');
$ok = hash_equals($expected, $got);

// C#
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = Convert.ToHexString(hmac.ComputeHash(rawBodyBytes)).ToLowerInvariant();
var ok = CryptographicOperations.FixedTimeEquals(
    Encoding.UTF8.GetBytes(expected),
    Encoding.UTF8.GetBytes(header.Replace("sha256=", "")));

エラー

  • 400 — リクエスト本文が JSON ではないか、必須項目が不足しているか無効です
  • 401 — キーが存在しないか、失効または期限切れです
  • 403 — このエンドポイントに必要な権限がキーにありません
  • 404 — このワークスペース内に指定された ID のドキュメントが見つかりません
  • 429 — 1分あたりの上限に達しました。時間を置いてから再試行してください
  • 500 — サーバー側でエラーが発生しました。詳細はレスポンスをご確認ください