検証済みワークフローAPI

API利用前にワークフローを検証

まずワークステーションで、確認済みの出力がワークフローに合っていることを確認してから、繰り返しの抽出実行にAPIを使用してください。

Base: https://pdf2text.ai/api/v1

認証

すべてのAPIリクエストには、AuthorizationヘッダーにBearerトークンが必要です。繰り返し使えるワークフローを検証した後、アカウント設定からキーを生成してください。

APIキーを管理
# Set your API key
export P2T_API_KEY="your_api_key_here"

# Include in all requests
curl -H "Authorization: Bearer $P2T_API_KEY" ...
import requests
import os

API_KEY = os.environ["P2T_API_KEY"]
headers = {"Authorization": f"Bearer {API_KEY}"}
const API_KEY = process.env.P2T_API_KEY;

const headers = {
  'Authorization': `Bearer ${API_KEY}`
};

利用制限

Firmプランには、確認を伴うワークステーションのワークフローと検証済みのAPI抽出実行のために、毎月1500ページが含まれます。処理されたページごとに、その枠から1ページが使用されます。

利用量はAPI呼び出し回数ではなく、処理されたページ数で計測されます。ファイルのアップロードや結果・エクスポートのダウンロードではページは使用されませんが、抽出を再実行するとそのページが再度処理され、ページが再び使用されます。

対応しているアップロード形式はPDF、PNG、JPEG、WebPで、1ファイルあたり最大50 MiBです。現在の環境では、すべてのファイルとフォームのオーバーヘッドを含むマルチパートリクエスト全体も100 MiBに制限されています。アップロードは、1リクエストあたり20ファイル、1グループあたり100ファイル、1ドキュメントまたは1実行あたり500ページ、1グループあたり保存ページ数1,000ページに制限されています。画像はいずれの辺も最大20,000ピクセル、40メガピクセルまでです。OCRのレンダリング解像度でこれらのラスター上限を超えるPDFページは拒否されます。

API呼び出しに個別の上限はありません。抽出の実行は非同期で処理キューに入るため、完了までの時間はドキュメントのサイズやシステムの負荷によって異なります。

フェアユースのリクエスト制限は、デフォルトで1アカウントあたり1時間に30回のアップロード、60回の実行開始、600回の読み取りまたはエクスポートです。429レスポンスにはRetry-Afterが含まれます。再試行する前に、その間隔だけ待ってください。

API自動化に頼る前に、ワークステーションを使ってドキュメントのレイアウト、確認ルール、エクスポート形式を検証してください。

プランを比較
POST

ドキュメントをアップロード

1つ以上のPDF、PNG、JPEG、WebPファイルをアップロードして、ドキュメントグループを作成します。ファイルのバイト、ページ数、画像のサイズは、保存前に検証されます。アップロードに成功すると、すべてのドキュメントについて検証済みのpage_countを含む201 Createdが返されます。

エンドポイント

POST /api/v1/documents/upload/

パラメータ

file / files binary PDF、PNG、JPEG、またはWebP(必須。複数アップロードする場合はfilesを繰り返します)
grouping_id uuid 任意。既存のAPIグループのいずれかに追加します。匿名のワークスペースはUUIDで引き継ぐことはできません。また、実行中のグループは完了するまで変更できません。
document_type string 任意。分類のヒント。
password string 任意。このリクエストでパスワード付きPDFを開きます。ファイルを開くためだけに使われ、保存されません。指定しない場合、そのPDFはencrypted_pdfを返します。誤ったパスワードはpdf_password_incorrectを返し、同じファイルで誤りが続くと429を返します。
# Upload a PDF file
curl -X POST https://pdf2text.ai/api/v1/documents/upload/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -F "file=@invoice.pdf"

# Add to existing group
curl -X POST https://pdf2text.ai/api/v1/documents/upload/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -F "file=@invoice2.pdf" \
  -F "grouping_id=a1b2c3d4-..."
import requests

url = "https://pdf2text.ai/api/v1/documents/upload/"

# Upload single file
with open("invoice.pdf", "rb") as f:
    response = requests.post(
        url,
        headers=headers,
        files={"file": f}
    )

data = response.json()
group_id = data["group_id"]
const { readFile } = require('node:fs/promises');

const form = new FormData();
form.append(
  'file',
  new Blob([await readFile('invoice.pdf')], { type: 'application/pdf' }),
  'invoice.pdf'
);

const response = await fetch(
  'https://pdf2text.ai/api/v1/documents/upload/',
  {
    method: 'POST',
    headers,
    body: form
  }
);
if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
const { group_id } = await response.json();
201 Created
{
  "status": "success",
  "group_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "documents": [
    {
      "doc_id": 42,
      "uid": "1847f600-...",
      "grouping_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "original_filename": "invoice.pdf",
      "file_type": "pdf",
      "page_count": 3,
      "status": "pending"
    }
  ]
}

グループにファイルを追加できるのは、最初の実行前のみです。後から追加する請求書には新しいグループを作成してください。そうしないと、フィルターなしの実行でそのグループ内の既存のドキュメントがすべて処理されます。

POST

抽出処理を開始

ドキュメントグループの非同期処理を開始します。抽出前にPDF2TEXTでドキュメントを分類する場合は、自動ルーティングを使用してください。

すべての開始リクエストでIdempotency-Keyヘッダーを送信してください。同じキーと本文を繰り返すと同じ実行が返されます。異なるリクエストにキーを再利用すると409が返されます。最終的な失敗の後は、新しいキーを使って意図的に代わりの実行を作成してください。新たにキューに入った実行には202 Acceptedが返されます。1つのグループで同時に実行できるのは1つだけで、実行中の処理は処理可能なアカウントのページを確保します。

202レスポンスは実行が受け付けられたことを示すものであり、要求されたすべてのページ分の残高があることを示すものではありません。アカウントの共有残高が実行に必要な量より少ない場合、APIは確保されたページを処理し、credit_limit_reached=trueのpartialとして完了します。インポートを完了として扱う前に、実行の最終ステータスを確認してください。

コールバックURLは公開されたHTTPSを使用する必要があり、別の宛先にリダイレクトすることはできません。配信は非同期で、リクエストのタイムアウトは10秒です。一時的な接続エラー、HTTP 429、HTTP 5xxのレスポンスに対しては、30秒、2分、10分のバックオフ間隔で最大4回再試行します。

callback_secretを指定した場合は、リクエスト本文そのものに対してHMAC-SHA256を計算し、sha256=の値と比較してX-PDF2TEXT-Signatureを検証してください。配信の重複排除には、X-PDF2TEXT-Run-IDまたはX-PDF2TEXT-Idempotency-Keyを使用してください。

The callback JSON body is {"event": "idp.run.completed", "run": {...}}; run uses the same full result shape as GET ?include=results. A signature header is sent only when callback_secret was included in the start request.

エンドポイント

POST /api/v1/groups/{group_id}/runs/

リクエストボディ

auto_route boolean 自動分類(デフォルト:true)
extraction_mode enum auto、raw_text、financial_table、general_table、またはunified。カスタムスキーマにはtemplate_idまたはtemplate_slugを使用してください。
template_id / template_slug uuid / string 特定のテンプレートを強制するには、いずれか1つだけを指定してください
selected_pages array {docUid, pageNumber}の空でないリスト(任意)。無効なページがあるとリクエスト全体が拒否されます
construction_project_id uuid APIアカウントが所有するプロジェクト(任意)
callback_url string Webhook URL
callback_secret string HMAC署名シークレット
# Start extraction with auto-routing
curl -X POST https://pdf2text.ai/api/v1/groups/$GROUP_ID/runs/ \
  -H "Authorization: Bearer $P2T_API_KEY" \
  -H "Idempotency-Key: invoice-import-123" \
  -H "Content-Type: application/json" \
  -d '{"auto_route": true}'
# Start extraction run
url = f"https://pdf2text.ai/api/v1/groups/{group_id}/runs/"

response = requests.post(
    url,
    headers={**headers, "Idempotency-Key": "invoice-import-123"},
    json={"auto_route": True}
)

run_data = response.json()
run_id = run_data["run_id"]
// Start extraction run
const response = await fetch(
  `https://pdf2text.ai/api/v1/groups/${groupId}/runs/`,
  {
    method: 'POST',
    headers: {
      ...headers,
      'Idempotency-Key': 'invoice-import-123',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ auto_route: true })
  }
);

const { run_id } = await response.json();
202 Accepted
{
  "status": "success",
  "run_id": "b3143b91-...",
  "job_id": "idp-run-b3143b91-...",
  "group_name": "ocr_job_a1b2c3d4...",
  "idempotent_replay": false,
  "run": {
    "id": "b3143b91-...",
    "status": "queued",
    "job_id": "idp-run-b3143b91-...",
    "total_pages": 3,
    "pages_processed": 0
  }
}
GET

結果を取得

runエンドポイントをポーリングするか、Webhookを使用して抽出結果を取得します。JSONまたはExcel形式でエクスポートできます。

デフォルトの実行レスポンスは頻繁なポーリング向けに軽量化されており、キャッシュされることはありません。ネストされたrunオブジェクト内のrun.statusを参照してください。最終ステータスはcomplete、partial、errorです。最終ステータスになった後、include=resultsを1回リクエストして、full_text、structured_output、documentsを取得してください。

credits_remainingは互換性のために残されており、その実行後の過去の残高を記録しています。credits_remaining_after_runは同じ過去の値を明示的に示すもので、account_credits_remainingはレスポンス生成時点のアカウントの現在の共有残高を示します。

エンドポイント一覧

GET /api/v1/runs/{run_id}/ GET /api/v1/runs/{run_id}/?include=results GET /api/v1/runs/{run_id}/export.json GET /api/v1/runs/{run_id}/export.xlsx GET /api/v1/runs/{run_id}/export.xlsx?date_format=MM/DD/YYYY

銀行明細の場合、export.xlsxにはQuickBooks CSVとXero CSVのシートも含まれます。日付はアカウントに保存した形式、なければ明細の国の並びで書き出されます。date_format(DD/MM/YYYY、MM/DD/YYYY、YYYY/MM/DD、YYYY-MM-DD)を渡すと指定でき、ほかのシートはYYYY-MM-DDのままです。

レスポンスステータスコード

200 401 404
# Lightweight status poll
curl https://pdf2text.ai/api/v1/runs/$RUN_ID/ \
  -H "Authorization: Bearer $P2T_API_KEY"

# Fetch completed results once, then export
curl "https://pdf2text.ai/api/v1/runs/$RUN_ID/?include=results" \
  -H "Authorization: Bearer $P2T_API_KEY"

curl -o results.xlsx \
  https://pdf2text.ai/api/v1/runs/$RUN_ID/export.xlsx \
  -H "Authorization: Bearer $P2T_API_KEY"
import time

run_url = f"https://pdf2text.ai/api/v1/runs/{run_id}/"
terminal = {"complete", "partial", "error"}
delay = 2

# Poll lightweight state with bounded exponential backoff
while True:
    response = requests.get(run_url, headers=headers)
    if response.status_code == 429:
        retry_after = int(response.headers.get("Retry-After", delay))
        time.sleep(retry_after)
        delay = min(30, max(10, delay * 2))
        continue
    response.raise_for_status()
    run = response.json()["run"]

    if run["status"] in terminal:
        break

    time.sleep(delay)
    delay = min(30, max(10, delay * 2))

if run["status"] == "error":
    raise RuntimeError(run["error_message"])

results = requests.get(run_url, params={"include": "results"}, headers=headers).json()["run"]

excel = requests.get(
    f"{run_url}export.xlsx",
    headers=headers
)
with open("results.xlsx", "wb") as f:
    f.write(excel.content)
// Poll lightweight state
const pollResults = async (runId) => {
  const runUrl = `https://pdf2text.ai/api/v1/runs/${runId}/`;
  const terminal = new Set(['complete', 'partial', 'error']);
  let delay = 2000;
  while (true) {
    const response = await fetch(runUrl, { headers });
    if (response.status === 429) {
      const retryAfter = Number(response.headers.get('Retry-After') || delay / 1000);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      delay = Math.min(30000, Math.max(10000, delay * 2));
      continue;
    }
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const { run } = await response.json();

    if (terminal.has(run.status)) {
      if (run.status === 'error') throw new Error(run.error_message);
      const resultResponse = await fetch(`${runUrl}?include=results`, { headers });
      return (await resultResponse.json()).run;
    }

    await new Promise(r => setTimeout(r, delay));
    delay = Math.min(30000, Math.max(10000, delay * 2));
  }
};

const results = await pollResults(runId);
include=resultsを指定したレスポンス
{
  "status": "success",
  "run": {
    "id": "b3143b91-...",
    "status": "complete",
    "total_pages": 3,
    "pages_processed": 3,
    "credits_remaining_after_run": 497,
    "account_credits_remaining": 497,
    "full_text": "...",
    "structured_output": { /* grouped output */ },
    "documents": [
      {
        "doc_id": 42,
        "document_name": "invoice.pdf",
        "ocr_text": "...",
        "structured_output": { /* document output */ }
      }
    ]
  }
}
GET

テンプレート

利用可能な抽出テンプレートを一覧表示します。テンプレートIDを使用して特定の抽出スキーマを指定できます。

エンドポイント

GET /api/v1/templates/
テンプレートを管理
# List available templates
curl https://pdf2text.ai/api/v1/templates/ \
  -H "Authorization: Bearer $P2T_API_KEY"
# List available templates
response = requests.get(
    "https://pdf2text.ai/api/v1/templates/",
    headers=headers
)

templates = response.json()["templates"]
for t in templates:
    print(f"{t['name']}: {t['id']}")
// List available templates
const response = await fetch(
  'https://pdf2text.ai/api/v1/templates/',
  { headers }
);

const { templates } = await response.json();
templates.forEach(t => console.log(`${t.name}: ${t.id}`));
レスポンス
{
  "status": "success",
  "templates": [
    {
      "id": "198aa5be-ea8b-4d67-bdb5-625f5d7d29e8",
      "slug": "invoice",
      "name": "Invoice",
      "description": "Standard invoice extraction",
      "extraction_mode": "financial_table"
    },
    {
      "id": "4317707a-f0da-4c2f-a1ec-d0119d96b55c",
      "slug": "receipt",
      "name": "Receipt",
      "description": "Receipt and expense extraction",
      "extraction_mode": "financial_table"
    }
  ]
}

サポートが必要ですか?

確認キューを使って、抽出されたフィールドを確認し、確認の経緯を保持してください。