> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API

Ingest は、`fineparser-ingest` Service のポート 8080 で API を提供します。ドキュメントを送信し、ジョブが完了するまでポーリングしたうえで、結果をダウンロードします。

この API には認証機能がありません。公開する前に、呼び出し元を認証する仕組みを API の前段に配置してください。詳しくは [API の公開](https://docs.abbyy.com/ja/fine-parser/enterprise/best-practices/production-deployment.md#exposing-the-api)を参照してください。

| エンドポイント | 用途 |
| - | - |
| `POST /parse` | 1 つ以上のドキュメントを送信します。 |
| `GET /jobs/{jobId}` | ジョブのステータスを取得します。 |
| `GET /batch/{batchId}` | 1 回のリクエストで作成されたすべてのジョブのステータスを取得します。 |
| `GET /jobs/{jobId}/{name}` | 結果をダウンロードします。 |

```bash cURL theme={null}
# 送信
curl -s -F files=@invoice.pdf -F outputTypes=json http://localhost:8080/parse
# {"jobs":[{"file":"invoice.pdf","jobId":"e08f769f-..."}]}

# ポーリング
curl -s http://localhost:8080/jobs/e08f769f-...
# {"status":"successful","files":["e08f769f-.../invoice.json"],...}

# ダウンロード
curl -OJ http://localhost:8080/jobs/e08f769f-.../invoice.json
```

```python Python theme={null}
import pathlib, time

import requests

FP = "http://localhost:8080"

with open("invoice.pdf", "rb") as f:
    r = requests.post(f"{FP}/parse", files={"files": f}, data={"outputTypes": ["json"]})
r.raise_for_status()
job = r.json()["jobs"][0]["jobId"]

while (status := requests.get(f"{FP}/jobs/{job}").json())["status"] in ("pending", "in-progress"):
    time.sleep(3)
if status["status"] != "successful":
    raise RuntimeError(status["failure"])

for entry in status["files"]:
    r = requests.get(f"{FP}/jobs/{entry}")
    r.raise_for_status()
    pathlib.Path(pathlib.Path(entry).name).write_bytes(r.content)
```

## POST /parse

`multipart/form-data` 形式のリクエストです。

| field | 必須 | 値 |
| - | - | - |
| `files` | はい | PDF ファイル、または PNG、JPEG、TIFF などの画像ファイル。複数のファイルを送信するには、このfieldを繰り返し指定します。 |
| `outputTypes` | はい | `doclang`、`json`、`xml`、`txt` のいずれか。複数指定するには、このfieldを繰り返し指定します。詳細は[出力形式](https://docs.abbyy.com/ja/fine-parser/enterprise/basics/output-formats.md)を参照してください。 |
| `baseProfile` | いいえ | 事前定義の認識プロファイル。`userIni` と併せて指定する必要があります。 |
| `userIni` | いいえ | ユーザープロファイル。fieldまたはファイルとして指定します。`baseProfile` と併せて指定する必要があります。詳細は[Recognition settings](https://docs.abbyy.com/ja/fine-parser/enterprise/basics/recognition-settings.md#per-request-profiles)を参照してください。 |

レスポンスは `202 Accepted` で、ファイルごとにジョブ ID が返されます。複数のファイルを送信した場合は、`batchId` も返されます。受け付けられなかったファイルは `errors` に一覧表示されます。

```json theme={null}
{"batchId":"c5a6dd90-...","jobs":[{"file":"a.pdf","jobId":"c2f11bb8-..."},{"file":"b.pdf","jobId":"2ab42551-..."}]}
```

`POST /parse` はべき等ではありません。タイムアウト後に再送信すると、ジョブが重複して作成される可能性があります。

## GET /jobs/{jobId}

| Field | 意味 |
| - | - |
| `status` | `pending`、`in-progress`、`successful`、`failed` のいずれか。 |
| `files` | `successful` の場合：結果ごとに 1 エントリ (`{jobId}/{name}` 形式) 。 |
| `durationSeconds` | `successful` の場合：送信から完了までの秒数。 |
| `failure` | `failed` の場合：`{"reason": ..., "message": ...}`。 |

完了したジョブのステータスは `orchestrator.jobRetentionSeconds` (デフォルトは 24 時間) の間保持されます。この期間を過ぎると、このエンドポイントは `404` を返しますが、結果は引き続きダウンロードできます。

| `reason` | 対処方法 |
| - | - |
| `profile-rejected` | メッセージで示されているプロファイル設定を修正してください。 |
| `ingest-failed` | ファイルが開けるか確認してください。ファイルが破損しているか、サポートされていない形式である可能性があります。 |
| `never-started` | もう一度送信してください。 |
| `recognition-failed` | もう一度送信してください。再び失敗する場合は、ドキュメントが読み取れない可能性があります。 |
| `finalize-failed` | 出力ボリュームを確認してから、もう一度送信してください。 |
| `timed-out` | [ユニットサイズとリース](https://docs.abbyy.com/ja/fine-parser/enterprise/concepts/scaling.md#unit-size-and-leases)を参照してください。 |

## GET /batch/{batchId}

リクエスト全体の `status` と `jobs` を返します。`jobs` には、各ジョブの `jobId`、`file`、`status` が `GET /jobs/{jobId}` と同じ形式で含まれます。バッチが `successful` になるのは、すべてのジョブが `successful` の場合のみです。

## GET /jobs/{jobId}/{name}

結果をダウンロードします。各 `files` エントリはすでに `{jobId}/{name}` の形式になっているため、そのまま `/jobs/` の後ろに連結してください。ダウンロードしても結果は削除されません。

## エラー

エラーは JSON 形式で返されます: `{"error":{"code":"...","message":"..."}}`。`code` の値に応じて処理を分岐してください。

| `code` | HTTP | 意味 |
| - | - | - |
| `invalid_request` | 400 | field が指定されていないか、無効です。該当する field はメッセージに示されます。 |
| `no_files_accepted` | 400 | 受け付け可能なファイルがありませんでした。各ファイルの理由は `errors` に示されます。 |
| `not_found` | 404 | 該当するジョブ、バッチ、ファイル、またはパスが存在しません。 |
| `method_not_allowed` | 405 | HTTP メソッドが正しくありません。 |
| `upload_too_large` | 413 | リクエストのサイズが `ingest.maxUploadSize` を超えています。 |
| `orchestrator_error` | 502 | 予期しない内部エラーが発生しました。 |
| `orchestrator_unavailable` | 503 | 一時的に利用できません。`Retry-After` に示された秒数が経過してから再試行してください。 |

## 制限

| 制限 | 設定 |
| - | - |
| リクエストサイズ (全ファイルの合計) | `ingest.maxUploadSize` |
| 1リクエストあたりのフォームパート数 (ファイルと `outputTypes` の合計) | 5,000 |
| `userIni` のサイズ | 1 MiB |

## CORS

別のオリジンのブラウザーから API を呼び出すには、`ingest.cors.allowedOrigins` に許可するオリジンをカンマ区切りで指定します。デフォルトでは、どのオリジンも許可されていません。
