Skip to content

抽出の実行

概要

抽出エンドポイントは、ドキュメント(base64エンコード済み)を受け取り、定義したテンプレートを通して処理し、テンプレートの変数に一致する構造化データを返します。1回のAPIコールでパイプライン全体(アップロード、AI処理、構造化出力)を処理します。

すべての抽出リクエストは POST /v1/extractions/run を経由します。

ドキュメントの準備

ドキュメントをAPIに送信する前に、ファイルの内容をbase64エンコードする必要があります。

制約:

  • リクエストボディの最大サイズ: 15 MB
  • サポートされるMIMEタイプ:
    • application/pdf (PDF)
    • application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX)
bash
# PDFファイルをBase64エンコード
base64 -i invoice.pdf -o invoice_b64.txt

# またはインライン(macOS / Linux)
PDF_BASE64=$(base64 -w 0 invoice.pdf)
typescript
import { readFileSync } from "fs";

const pdfBuffer = readFileSync("invoice.pdf");
const pdfBase64 = pdfBuffer.toString("base64");
python
import base64

with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

WARNING

Base64エンコードにより、ファイルサイズは約33%増加します。10 MBのPDFはエンコード後に約13.3 MBになるため、15 MBのリクエスト制限内に収まるよう、元ファイルは約11 MB以下にしてください。

リクエストの送信

以下のJSONボディで POST リクエストを /v1/extractions/run に送信します:

フィールド必須説明
templateIdstringはい抽出に使用するテンプレートのID
fileNamestringはい元のファイル名(例:"invoice.pdf"
pdfBase64stringはいBase64エンコードされたファイルの内容
mimeTypestringはいファイルのMIMEタイプ
runIdstringいいえ複数の抽出をバッチにグループ化するためのオプションの識別子
bash
curl -X POST https://api.docmap.io/v1/extractions/run \
  -H "Authorization: Bearer dm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_abc123",
    "fileName": "invoice.pdf",
    "pdfBase64": "JVBERi0xLjQKJeLj...",
    "mimeType": "application/pdf"
  }'
typescript
const response = await fetch("https://api.docmap.io/v1/extractions/run", {
  method: "POST",
  headers: {
    Authorization: "Bearer dm_live_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: pdfBase64,
    mimeType: "application/pdf",
  }),
});

const { data } = await response.json();
console.log(data.extractedData);
python
import requests

response = requests.post(
    "https://api.docmap.io/v1/extractions/run",
    headers={
        "Authorization": "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
    },
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

data = response.json()["data"]
print(data["extractedData"])

レスポンスの理解

抽出が成功すると、data オブジェクトでラップされたレスポンスが返されます:

json
{
  "data": {
    "id": "ext_abc123def456",
    "userId": "user_789",
    "templateId": "tmpl_abc123",
    "templateName": "Invoice Parser",
    "fileName": "invoice.pdf",
    "status": "completed",
    "extractedData": {
      "vendor_name": "Acme Corp",
      "invoice_number": "INV-2024-001",
      "total_amount": 1250.00,
      "line_items": [
        { "description": "Widget A", "quantity": 10, "unit_price": 125.00 }
      ]
    },
    "error": null,
    "variables": [
      { "name": "vendor_name", "type": "string", "description": "Company name of the vendor" },
      { "name": "invoice_number", "type": "string", "description": "Invoice reference number" },
      { "name": "total_amount", "type": "number", "description": "Total invoice amount" },
      { "name": "line_items", "type": "array", "description": "List of line items" }
    ],
    "source": "api",
    "runId": null,
    "processingTimeMs": 3420,
    "createdAt": "2025-07-15T10:30:00.000Z"
  }
}
フィールド説明
id一意の抽出ID(ext_ プレフィックス付き)
status実行中(非同期モード)は "processing"、データが正常に抽出された場合は "completed"、処理中にエラーが発生した場合は "failed"
extractedDataテンプレートの変数名に一致するキーを持つオブジェクト。抽出が失敗した場合は null
error抽出が失敗した場合のエラーメッセージ文字列。成功時は null
processingTimeMsAIがドキュメントを処理するのにかかった時間(ミリ秒)
sourceAPIキー経由でトリガーされた場合は "api"、Web UIからトリガーされた場合は "dashboard"
variablesこの抽出に使用されたテンプレート変数定義
runId指定したバッチ識別子、または指定なしの場合は null
templateName使用されたテンプレートの人間が読める名前
createdAt抽出が作成されたISO 8601タイムスタンプ

TIP

extractedData にアクセスする前に、必ず status フィールドを確認してください。status"failed" の場合、error フィールドに何が問題だったかの説明が含まれています。

バッチ抽出

複数のファイルを論理的なバッチとして処理するには、各抽出リクエストに同じ runId を渡します。これはドキュメントの処理方法を変えるものではありません -- 各ファイルは個別に抽出されます -- ただし、バッチからのすべての結果をまとめてクエリできるようになります。

typescript
const runId = "batch-invoices-2025-07";
const files = ["invoice-001.pdf", "invoice-002.pdf", "invoice-003.pdf"];

// 同じrunIdで各ファイルを処理
const results = await Promise.all(
  files.map(async (fileName) => {
    const pdfBase64 = readFileSync(fileName).toString("base64");

    const response = await fetch("https://api.docmap.io/v1/extractions/run", {
      method: "POST",
      headers: {
        Authorization: "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        templateId: "tmpl_abc123",
        fileName,
        pdfBase64,
        mimeType: "application/pdf",
        runId,
      }),
    });

    return response.json();
  })
);

次に、バッチからすべての抽出を取得します:

bash
curl "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07" \
  -H "Authorization: Bearer dm_live_your_api_key"
typescript
const response = await fetch(
  "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07",
  {
    headers: { Authorization: "Bearer dm_live_your_api_key" },
  }
);

const { data } = await response.json();
console.log(`Batch contains ${data.length} extractions`);
python
response = requests.get(
    "https://api.docmap.io/v1/extractions",
    params={"runId": "batch-invoices-2025-07"},
    headers={"Authorization": "Bearer dm_live_your_api_key"},
)

data = response.json()["data"]
print(f"Batch contains {len(data)} extractions")

TIP

一覧エンドポイントは templateId によるフィルタリングと limit パラメータ(1〜100、デフォルト50)もサポートしています。フィルタを組み合わせることができます: ?runId=batch-001&templateId=tmpl_abc123&limit=100

非同期ワークフロー

デフォルトでは、抽出リクエストは同期的です -- APIは処理が完了するまでブロックします。長時間実行される抽出の場合やHTTPタイムアウトを回避したい場合は、URLに ?async=true を追加して非同期モードを使用します。APIは即座に "processing" ステータスで応答し、結果の準備ができるまで別のエンドポイントをポーリングします。

送信 + ポーリングパターン

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

// 1. 非同期で抽出を送信
const submitResponse = await fetch(`${API_BASE}/v1/extractions/run?async=true`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: readFileSync("invoice.pdf").toString("base64"),
    mimeType: "application/pdf",
  }),
});

const { data: submitted } = await submitResponse.json();
console.log(`Extraction ${submitted.id} submitted, status: ${submitted.status}`);

// 2. 完了までポーリング
async function poll(extractionId: string): Promise<any> {
  for (let i = 0; i < 30; i++) {
    const res = await fetch(`${API_BASE}/v1/extractions/${extractionId}`, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });
    const { data } = await res.json();
    if (data.status !== "processing") return data;
    await new Promise((r) => setTimeout(r, 2000));
  }
  throw new Error("Extraction timed out");
}

const result = await poll(submitted.id);
console.log(`Final status: ${result.status}`);
console.log("Extracted data:", result.extractedData);
python
import base64
import time
import requests

API_BASE = "https://api.docmap.io"
API_KEY = "dm_live_your_api_key"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# 1. 非同期で抽出を送信
with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

submit_response = requests.post(
    f"{API_BASE}/v1/extractions/run?async=true",
    headers=headers,
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

submitted = submit_response.json()["data"]
print(f"Extraction {submitted['id']} submitted, status: {submitted['status']}")

# 2. 完了までポーリング
def poll(extraction_id: str):
    for _ in range(30):
        res = requests.get(
            f"{API_BASE}/v1/extractions/{extraction_id}",
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        data = res.json()["data"]
        if data["status"] != "processing":
            return data
        time.sleep(2)
    raise TimeoutError("Extraction timed out")

result = poll(submitted["id"])
print(f"Final status: {result['status']}")
print("Extracted data:", result["extractedData"])

非同期モードを使用するタイミング

大きなドキュメントを処理する場合、HTTPクライアントのタイムアウトが短い場合、または複数の抽出を送信して後で結果を収集したい場合に非同期モードを使用してください。ほとんどの単一ドキュメントの抽出には、同期モードの方がシンプルです。

完全なワークフロー例

以下は、ディスクからPDFを読み込み、抽出を実行し、成功と失敗の両方を処理するTypeScriptによるエンドツーエンドの完全な例です:

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

async function extractInvoice(filePath: string) {
  // 1. PDFを読み込みエンコード
  const pdfBuffer = readFileSync(filePath);
  const pdfBase64 = pdfBuffer.toString("base64");
  const fileName = filePath.split("/").pop()!;

  console.log(`Processing ${fileName} (${(pdfBuffer.length / 1024).toFixed(0)} KB)...`);

  // 2. 抽出を実行
  const response = await fetch(`${API_BASE}/v1/extractions/run`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      templateId: "tmpl_invoice_parser",
      fileName,
      pdfBase64,
      mimeType: "application/pdf",
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.error.message}`);
  }

  const { data } = await response.json();

  // 3. 抽出結果を確認
  if (data.status === "failed") {
    console.error(`Extraction failed: ${data.error}`);
    return null;
  }

  console.log(`Extraction completed in ${data.processingTimeMs}ms`);
  console.log("Extracted data:", JSON.stringify(data.extractedData, null, 2));

  return data.extractedData;
}

// 実行
extractInvoice("./invoices/invoice-001.pdf")
  .then((result) => {
    if (result) {
      console.log(`Vendor: ${result.vendor_name}`);
      console.log(`Total: $${result.total_amount}`);
    }
  })
  .catch(console.error);

DocMap API ドキュメント