API ドキュメント

ひとつのエンドポイント。フォーマットバージョン 4。ベース URL https://api.consensis.app。

認証

すべてのリクエストに API キーを付けます — Authorization: Bearer pk_live_… または X-API-Key ヘッダー。サインイン(Google またはメール。サインインでアカウントが作成されます)して、アカウントページでキーを発行してください。平文のキーは 1 回だけ表示され、当社はダイジェストのみ保存します。照合できないキーは 401 を返します — 打ち間違えたキーが黙って匿名トライアルに降格されることはないので、ジョブがどのアカウントに請求されたかは常に分かります。

匿名トライアル: API では 1 接続元あたり 1 日 10 ページ無料 — さらにWeb アップローダーでも 1 日 10 ページ — アカウント不要。有料利用は前払い — 納品 1 ページあたり 0.06(mode=batch なら 0.036)、最低チャージ 3.50。失敗したページは請求しません。

無料で試す — キー不要、アカウント不要

無料トライアルは API から直接使えます:1 接続元あたり 1 日 10 ページ無料、Authorization ヘッダーはまったく不要です(Web アップローダーには別枠で 10 ページがあります。枠を超えるとレスポンスに Retry-After が付きます)。

# 完全に匿名 — キー不要、登録不要
curl -X POST https://api.consensis.app/v1/parse -F "[email protected]"
# → 202 {"id": "…", "status": "queued", ...} — 以下と同じ方法でポーリング

3 行で始める

curl -X POST https://api.consensis.app/v1/parse \
     -H "Authorization: Bearer pk_live_…" \
     -F "[email protected]" -F "pages=10"
# → 202 {"id": "b7f395cf7fbc", "status": "queued", ...}

curl -H "Authorization: Bearer pk_live_…" \
     https://api.consensis.app/v1/parse/b7f395cf7fbc
# → "status": "done" になるまでポーリング。そのとき usage と result が含まれる

curl -OJ -H "Authorization: Bearer pk_live_…" \
     "https://api.consensis.app/v1/parse/b7f395cf7fbc/export?format=xlsx"
エクスポート形式の選び方: json と zip はすべて(信頼度、ソース、読み取り結果、bbox)を含みます。xlsx は信頼度フラグを目に見える形で残します — 不一致のセルは赤、未検証は黄色の網掛け — さらに監査用の平坦な cells シート付き。csv は値のみ:どのセルが不一致かを表現できないので、信頼性が重要な場面では JSON と組み合わせてください。

非同期 — POST は即座に 202 を返します。id で追跡してください。10 ページはコールドで約 600 秒、キャッシュヒットならはるかに速くなります。stage から完了を推測しないでください — あの文字列は人間向けです。status を見てください。

Batch モード — 1 ページ 0.036: POST に -F "mode=batch" を追加します。同じ抽出、同じ保証、同じ結果の形式。異なるのは所要時間のみで、片方の読み取り処理を batch エンドポイントで実行します。9 回の実測では 4〜55 分でしたが、これは観測値であり保証値ではありません。上流の batch サービスは目標時間を 24 時間と明言しています。当社がお約束する最低保証は、batch 側の処理が 4 時間以内に完了しない場合、リアルタイムパイプラインで再実行し、batch 価格のまま結果をお届けすることです。差額は当社が負担します。ポーリング方法は同一で、ジョブは "mode": "batch" を返します。レイテンシより価格を優先する夜間実行や大規模なバックフィルに最適です。

すべてのセルが持つもの

この API が売っているのはこれです。「より良い抽出」ではなく — すべてのセルが自分の根拠を説明できること。

{"value": "1432",
 "confidence": "verified",
 "sources": ["vision-1", "vision-2"],
 "bbox": [436.5, 577.7, 459.8, 591.9]}

独立した 2 つの読み取りが一致したので、このセルは verified で readings を持ちません — 値がそのまま値です。

readings が決定的な違いです:読み取りが食い違ったときは、すべての版をお渡しします — 黙ってひとつを選ぶことはしません。選んだものが間違っていたら、どこを見ればいいのか手がかりがなくなるからです。不一致があるときだけ現れます:

{"value": "1432",
 "confidence": "disputed",
 "provisional": true,
 "sources": ["vision-1", "vision-2"],
 "readings": {"vision-1": "1432", "vision-2": "1482"}}

provisional

confidence が disputed のときだけ現れ、常に true です。

ソースが食い違っても値は納品します — データは使えなければならず、空セルは黙って失われた値だからです。ただしその値は暫定です:行動する前に readings と照合し、本番システムに直接取り込まないでください。

confidence

confidence意味
exact構造化ファイルから直接読み取り — 解釈は一切介在しない
verified複数の独立した読み取りが一致
confirmed人が元ページを見て確定
reviewedAI レビュアーが元ページ画像と照合して裁定 — 速く実測済みだが、独立して検証されたわけではない
resolved読み取りの過半数が一致
unverified読み取りが1つのみ — 照合対象がない
disputed独立した読み取りが食い違う — 人の確認が必要なセル

sources

これはベンダー名ではありません。 監査が問うのは「独立した読み取りがいくつあるか」であって、「どのベンダーか」ではありません。

sources内容
ocr-1あるモデル系統の OCR エンジン
ocr-2別の系統の OCR エンジン — 同一ソースの偏りを捉えられるのは異なる系統だけ
ocr-3第三の OCR 系統。現在のサービスでは無効 — 当社の構成が変わっても契約が変わらないよう、名前は語彙に残している。
pdf-layoutPDF 自身のレイアウト幾何(罫線とテキストレイヤーがあれば最も正確 — しかも無料)
pdf-grid塗りつぶし矩形から推定したグリッド線
pdf-modelPDF の内部構造を読む学習済みレイアウトモデル — OCR なし、罫線に依存しない
pdf-textPDF のテキストレイヤー
source-data構造化ファイル(XLSX/CSV — 解釈なし)から直接読み取り
vision-review元のページ画像と照らして裁定
layoutレイアウト読み取りがこの位置に図を見つけた
ocr第二の読み取りが独立して同じ枠に重なる図を見つけた — 画像を verified にするのはこれ
pdf-imagePDF 自体がこの位置に埋め込み画像オブジェクトを持っている。これ単独では第二の意見にならない — ファイルに画像があると言っているだけで、正しい枠を切り出したことの裏付けではない
vision-1独立した 2 つのビジョンリーダーの一方。それぞれページ画像を見て表のグリッドを再構成する
vision-2第二のビジョンリーダー — vision-1 とは異なるモデル系統なので、両者は独立して食い違える
vision-singleビジョンで読んだが、このセルには読み取りが 1 つしかない — 第二の意見による裏付けがない
vision-auditconfirmed by the audit pass — a separate reading of the original page image that reviewed the whole table and raised no objection to this cell.
vision-arbiter2 つのビジョンリーダーの不一致を裁定した追加の読み取り — 2 つのうちの一方ではない
vision-grid初回の読み取りに穴やずれた行があった箇所を、ページ画像を読み直してグリッドを再構成して回復
human-review並列表示のレビューページで人が確認 — 他のソースはすべてページを解釈するもの。これは人が確定または修正したもの

bbox

[x0, y0, x1, y1]、PDF ポイント(1/72 インチ)、原点は左上。ページ番号は表の page にあります。

カバー率は 100% ではなく、ドキュメントによって大きく変わります(実測 3%〜48%)。usage.cells_with_bbox がお手元のドキュメントで bbox を持つセル数を正確に報告します — 数字は隠しません。

表の形

上の節はひとつのセルが何を持つかを述べました。ここでは表がその周りにどう形作られるかを述べます。

{
 "page": 7,
 "index": 0,
 "order": null,
 "kind": null,
 "layout_disputed": true,
 "column_major": false,
 "header": [
  "model",
  "d"
 ],
 "row_groups": [],
 "header_cells": [
  {
   "value": "model",
   "confidence": "unverified",
   "sources": []
  },
  {
   "value": "d",
   "confidence": "unverified",
   "sources": []
  }
 ],
 "rows": [
  [
   {
    "value": "LB 08",
    "confidence": "unverified",
    "sources": []
   },
   {
    "value": "1432",
    "confidence": "verified",
    "sources": [
     "vision-1",
     "vision-2"
    ]
   }
  ]
 ]
}

header はプレーンな列名です — header_cells から導出され、別に計算されることはないので、両者がずれることはありません。header_cells は同じ名前に confidence と sources を付けたもの:列名がひとつ間違えば列全体の意味が変わり、見ただけでは分かりません。

rows は行のリストで、各行はセルのリストです。column_major は元の表が横方向か縦方向かを示します。納品は常に行単位で、これはページがどうだったかの記録です。

row_groups は仕様表で見られる回転した側面の分類(Dimensions (mm)、Load capacity)です — 行ごとにラベルひとつ。列ではありません。列数は照合の土台だからです。しかしこれがないと C₀ が荷重なのか長さなのか分かりません。表にグループ分けがなければ空です。

該当するときだけ現れるフィールド

これらは unreadable と同じ規則に従います:すべての表に false があるのはノイズで、探したいのは例外のほうです。

フィールド現れるとき
caption表全体にかかる修飾語(例:HG - 15, 20)。納品時に属していたグループから継承。
kind当社が推定した表の種類。すべての表にあり、値は短いラベルであって保証ではない。
layout_disputedレイアウト読み取りの間で、ここに表があるかどうかの一致がない。 それでも抽出したものは納品する — ただし信頼する前に元ページと照合すること。これはセル単位の confidence とは別の軸:値が正しく読めたかではなく、表が存在するかを問うている。
ocr_unsupportedこの表に重なる内容を、独立した OCR 読み取りが見つけられなかった。上と同じ考え方:フラグを付け、捨てない。
span_grid行や列をまたぐセルを持つ表の背後にある結合セルグリッド。受け取る平坦な rows はこのグリッドを平坦化したもので、こちらが元の形。
colbands列バンド — 複数の列をひとつのラベルの下にまとめるヘッダー。
unfoldedこの表は折り込みページをまたいで再構成された。
sheetワークシート名。スプレッドシート入力のみで、現在は無効 — スプレッドシートを再開したとき契約が変わらないよう、フィールドの説明は残している。
注文コードは追加であって、置き換えではありません。 表が段階式の注文コード表であれば、segments(コードの各部分:名称と許容される値)と example_code をひとつ、追加で納品します。表そのものは変更なしで納品されます — すでに読んでいるものはそのまま動きます。

各表は bbox も持ちます — セル、本文、画像と同じ PDF ポイント座標での、表全体のページ上の枠(その表のセルの枠の和。どのセルにも枠がないときは付きません) — そして order、ページの読み順における位置。レイアウト読み取りの間でページの表の数が食い違うときは、order は代わりに bbox から測ります:表の上にある最後の本文または画像ブロックの order と等しくなります。pages[].width/height と合わせれば、ページを構造化レイアウトとして再構成するのに十分です。

本文と画像

結果は tables だけではありません。すべてのドキュメントに prose(本文 — 見出しと段落)と images(切り抜いた図)も含まれます。どちらもセルと同じ方法で照合され、どちらも誰が裏付けたかを示します。

prose

{"page": 7,
 "index": 2,
 "text": "Preload classes are selected according to the rail size.",
 "confidence": "verified",
 "sources": ["ocr-1", "ocr-2"],
 "bbox": [56.2, 98.6, 213.6, 236.9],
 "role": "paragraph",
 "level": 0,
 "order": 4}

テキストブロックごとに 1 エントリ、ページ単位で番号付け。role は heading または paragraph。level は見出しの深さ(段落は 0)。order はページの読み順における位置で、images と共有しているので交互に並べられます。

テキストを出力した読み取りは、自分自身の証人としては数えません。 段落が verified になるのは、ページの別の読み取りが同じ内容を含むときです — つまり表示されるソースは一致した側であって、検査される側ではありません。段落の境界は一致しなくて構いません:読み取りごとにテキストの分け方は違い、それは書式の違いであって不一致ではありません。

実測:7 ドキュメント(2,812 段落)で、段落の 83〜91% が verified で返ります。ばらつきは実在し、ドキュメントに依存します — bbox と同じ注意書きです。スキャンは下限側に位置します。

images

{"page": 7,
 "index": 1,
 "path": "images/p007_00.png",
 "confidence": "verified",
 "bbox": [56.2, 98.6, 213.6, 236.9],
 "order": 3,
 "also_on": [9],
 "sources": ["layout", "ocr", "pdf-image"]}

path は結果バンドル(zip エクスポート)からの相対パス。also_on はバイト単位で同一のコピーを持つ他のページを列挙します — 重複は報告し、除去しません。同じ寸法図が 2 つの品番の下に正当に現れるからです。

画像は独自のソース語彙を使います。問いが「この値は正しく読めたか」ではなく「ここに図があるか」だからです。何が画像を verified にしないかに注意:pdf-image 単独です。PDF がその位置に埋め込み画像を持つことは、ファイルに絵があると言っているだけで、正しい枠を切り出したことの裏付けではありません — 以前のバージョンはこれを十分とみなし、3 つのドキュメントが 100% verified で返ってきた一方で、「図をまるごと見落とす」確率は構造的にゼロでした。

pages

[{"page": 6, "width": 612.0, "height": 792.0},
 {"page": 7, "width": 612.0, "height": 792.0, "unreadable": true}]

ページ範囲を指定した場合、その隣に source_pages が付きます:納品物での位置を元ファイルのページ番号に対応付けるので、結果は常に出所のページを指し示せます。

リクエストしたページごとに 1 エントリ。width と height は PDF ポイントでのキャンバスサイズ — これがないと bbox の置き場がありません。

unreadable: true は「このページに表がなかった」という意味ではありません。 ページを読み、独立した両方の読み取りが失敗したという意味です — そのページからは何もこの納品物に入っておらず、元ページを確認すべきです。本当に何もないページにはフラグは一切付きません。

このフラグは失敗したページにだけ現れるので、探すのは安上がりです。1 ページの失敗がドキュメント全体を道連れにすることはもうありません:他のページは通常どおり納品されます。すべてのページが失敗した場合は、空の結果を渡す代わりにジョブを拒否します。

制限

制限値この数字の理由
ファイルサイズ600 MB実在のスキャンカタログ(121、266、443、456 MB)から実測 — 推測ではありません。
ページ数500 ページ当社が測った最も厚いカタログは 235 ページで、500 ページのドキュメント 1 件でキューを約 2 時間占有します — それ以上だと 1 件のジョブが後ろの全員を待たせてしまいます。無料トライアルは 10 ページまで。セルフホスト環境では PDFPAGES_MAX_PAGES で調整できます。
形式PDF拡張子は見ません — 内容を見ます。 画像とスプレッドシートは現在無効です — パイプラインは対応していますが、独自の価格設定を伴って再開します。
同時実行一度に 1 ドキュメントパイプラインは CPU を使い切るため、キューはワーカー 1 つです。追加の送信はキューに並びます — 失敗はしません。
再起動再キューは最大 2 回サービス再起動で中断されたジョブは再キューされます(キャッシュ済みなので再実行のコストはほぼゼロ)。それを超えると、永遠にループする代わりに正直に失敗します。
保持期間完了から 24 時間お客様のデータは保持しません。 結果は同期的に取得できます。切り抜きは期間内に取得してください — その後、OCR キャッシュを含むジョブ全体が削除されます。DELETE /v1/parse/{id} でより早く削除できます。トレードオフ:同じドキュメントを後で再送すると新しいジョブとして処理 — 課金 — されます。近道になるコピーは残りません。
User-Agent を設定してください。 Python 標準ライブラリのデフォルト UA(Python-urllib/3.x)のリクエストは、当社に届く前に CDN のボット規則で拒否されます — CDN のエラーページが返り、下記のエラーのどれでもないので、サービスが落ちているように見えます。requests、httpx、curl はそのままで問題ありません。urllib では任意の User-Agent を自分で設定してください。

エラー

常に {"detail": "…"}、人間向けに書かれています — サーバーパスもキー名も決して含みません。

ステータス発生条件備考
400認識できない形式拡張子は見ません — 内容を見ます。対応形式:PDF。
401不明な API キーAuthorization / X-API-Key のキーがどのアカウントにも一致しません。入力ミスしたキーが匿名トライアルに降格されることはありません。意図してトライアルを利用する場合はキーを省略してください。
400無効にしている形式現在は一時的に PDF のみ受け付けています。画像とスプレッドシートはパイプラインでは対応していますが無効です — 独自の価格設定を伴って再開します。上のエラーとは別物です:ファイルは問題なく、今は受け付けていないだけです。
400ファイルが大きすぎる、または空上限は 600 MB です。
400pages が 1 未満必要なだけのページ数を指定してください。上限はサーバー側で適用します。
400未対応のエクスポート形式GET は xlsx、csv、json、zip(結果バンドル:dataset.json とすべての切り抜き画像)を受け付けます。POST /v1/export は xlsx と csv を受け付けます。
413ステートレスエクスポートの本体が大きすぎるPOST /v1/export は 600 MB までのデータセットを受け付けます。
402残高不足前払いプラン:このドキュメントの費用(ページ数 × ページ単価)が残高を超えている — ジョブは残高で賄えるときだけ実行されます。レスポンスには残高と、このドキュメントに必要な額が記載されます — チャージして再送してください。何もキューに入らず、何も請求されません。
429匿名トライアルのレート制限登録不要のトライアルには時間別・日別のページ上限があります(不正利用対策であって価格設定ではありません)。レスポンスには Retry-After が付きます。サインイン済みの前払いアカウントには適用されません。
404抽出が見つからないjob_id が間違っているか、サービスが再起動してこのジョブが復元されなかった。
404何も切り抜いていないのに format=zipバンドルは切り抜き画像と dataset.json です。図を 1 つも切り抜かなかったドキュメント(スプレッドシート、または純粋なテキストのページ)にはバンドルがありません。他の 3 形式は使えます — json は同じデータを含みます。結果に見えてそうではないアーカイブをお渡しするより、404 を返す仕様にしています。
409完了前にエクスポートを要求まず status が done になるまでポーリングしてください。
500完了したが結果ファイルがないこれは当社側のバグです。まだ実行中のふりをして永遠にポーリングさせることはしません。

ないもの

提供していないもの理由
POST /v1/webhooks完了コールバック。当面は GET /v1/parse/{id} をポーリングしてください。10 ページ(コールドで約 600 秒)ならポーリングで十分です。
page_range指定できるのは先頭 N ページだけで、100〜110 ページのような範囲指定はできません。 厚いカタログでは本当の制約です:235 ページのカタログは仕様表を後半に置いており、pages は 1 ページ目から数えます。
GET /v1/jobs, POST /v1/cancel/{id}一覧とキャンセル。まだ必要ないので作っていません。(削除はあります:DELETE /v1/parse/{id}。)

正直なところ

スキャンPDFでは精度が著しく低下します。 PDFのテキストレイヤーを独立した追加情報として読み取りに利用しているため、テキストレイヤーがない場合、当社の実測でクロスチェックのカバー率が 1/3〜1/18 に低下します。text_layer の有無は 202 レスポンスで返されるため、処理完了を待たずに確認できます。

精度はドキュメントによって大きく変わります。 測定方法、サンプル数、失敗する箇所は、人手で確認した下限値とともに文書化しています。ここに一律の「99%+」は書きません。