# EasyLink EasyDoc-Extract Document Information Extraction

## Overview

EasyDoc-Extract is an intelligent document information extraction model. After uploading a document (PDF/image), the model automatically extracts structured information and returns the results in JSON format. It is suitable for scenarios such as contract key field extraction, invoice parsing, and form data entry.

This interface uses async mode: submit a task to obtain a task ID, then poll to query the result.

For more details, see the [EasyLink official documentation](https://docs.easylink-ai.com/docs/capabilities/extraction/universal).

**Request URL**: `https://api-us-ca.umodelverse.ai/v1/tasks/submit`

## Supported Models

- `easydoc-extract`

## Extraction Mode Description

| Mode | Trigger Condition | Description |
| :--- | :--- | :--- |
| Closed-form | `parameters.json_schema` is valid JSON | Extracts fields according to the specified schema, result is a structured JSON object |
| Custom Prompt | `parameters.json_schema` is invalid + `parameters.prompt_cus` is non-empty | Extracts according to natural language description, result is a string |
| Open-form | Both are empty | Automatically identifies document type and extracts all recognizable fields |

## Request Parameters

### Submit Task

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| model | string | Yes | Model name, fixed as `easydoc-extract` |
| input.img_url | string | Yes | URL of the file to extract from; supports PDF / JPG / PNG / BMP / TIFF |
| parameters.json_schema | string | No | Closed-form mode: JSON Schema format string specifying fields to extract |
| parameters.prompt_cus | string | No | Custom Prompt mode: natural language description of extraction requirements |

`parameters.json_schema` example (closed-form mode, extracting contract key fields):

```json
{
  "type": "object",
  "properties": {
    "Party A Name": {"type": "string"},
    "Party B Name": {"type": "string"},
    "Contract Amount": {"type": "string"},
    "Signing Date": {"type": "string"},
    "Contract Number": {"type": "string"}
  }
}
```

### Query Task Status

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| task_id | string | Yes | Task ID returned when the task was submitted |

## Response Fields

### Submit Response

| Field | Type | Description |
| :--- | :--- | :--- |
| output.task_id | string | Task ID for subsequent queries |
| request_id | string | Request ID |

### Status Query Response

| Field | Type | Description |
| :--- | :--- | :--- |
| output.task_status | string | Task status: `Pending` / `Running` / `Success` / `Failure` |
| output.result | array | List of extraction results (returned on success), each element corresponds to one file |
| output.error_message | string | Error message (returned on failure) |
| usage.page_count | integer | Total number of pages in the file, used for billing |

Structure of each element in `output.result`:

| Field | Type | Description |
| :--- | :--- | :--- |
| page_count | integer | Number of pages in the current file |
| key_index | array | List of extracted field names (returned in closed-form mode) |
| extracted_fields | object/string | Extraction result: JSON object in closed-form mode, string in custom prompt mode |

## Examples

### Curl Examples

**Submit Task (Closed-form mode):**

```bash
curl -X POST https://api-us-ca.umodelverse.ai/v1/tasks/submit \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "easydoc-extract",
    "input": {
      "img_url": "https://example.com/contract.pdf"
    },
    "parameters": {
      "json_schema": "{\"type\":\"object\",\"properties\":{\"Party A Name\":{\"type\":\"string\"},\"Party B Name\":{\"type\":\"string\"},\"Contract Amount\":{\"type\":\"string\"},\"Signing Date\":{\"type\":\"string\"}}}"
    }
  }'
```

**Submit Task (Open-form mode):**

```bash
curl -X POST https://api-us-ca.umodelverse.ai/v1/tasks/submit \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "easydoc-extract",
    "input": {
      "img_url": "https://example.com/document.pdf"
    }
  }'
```

**Query Task Status:**

```bash
curl "https://api-us-ca.umodelverse.ai/v1/tasks/status?task_id={task_id}" \
  -H "Authorization: Bearer {api_key}"
```

### Python Example

```python
import json
import time
import requests

api_key = "YOUR_API_KEY"
base_url = "https://api-us-ca.umodelverse.ai/v1"

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
}

# Submit task (closed-form mode)
json_schema = {
    "type": "object",
    "properties": {
        "Party A Name": {"type": "string"},
        "Party B Name": {"type": "string"},
        "Contract Amount": {"type": "string"},
        "Signing Date": {"type": "string"},
    },
}

submit_data = {
    "model": "easydoc-extract",
    "input": {
        "img_url": "https://example.com/contract.pdf",
    },
    "parameters": {
        "json_schema": json.dumps(json_schema),
    },
}

resp = requests.post(f"{base_url}/tasks/submit", headers=headers, json=submit_data)
task_id = resp.json()["output"]["task_id"]
print(f"task_id: {task_id}")

# Poll for results
while True:
    result = requests.get(
        f"{base_url}/tasks/status",
        headers=headers,
        params={"task_id": task_id},
    ).json()

    status = result["output"]["task_status"]
    print(f"status: {status}")

    if status == "Success":
        print("Extraction result:")
        for item in result["output"]["result"]:
            print(f"  Pages: {item.get('page_count')}")
            print(f"  Field names: {item.get('key_index')}")
            print(f"  Extracted content: {item.get('extracted_fields')}")
        print(f"Total pages: {result['usage']['page_count']}")
        break
    elif status == "Failure":
        print(f"Failed: {result['output'].get('error_message')}")
        break

    time.sleep(5)
```

## Response Examples

**Submission successful:**

```json
{
  "output": {
    "task_id": "b_extract_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  },
  "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

**Task completed (closed-form mode):**

```json
{
  "output": {
    "task_id": "b_extract_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "task_status": "Success",
    "result": [
      {
        "page_count": 5,
        "key_index": ["Party A Name", "Party B Name", "Contract Amount", "Signing Date"],
        "extracted_fields": {
          "Party A Name": "Example Technology Co., Ltd.",
          "Party B Name": "Example Trading Co., Ltd.",
          "Contract Amount": "One Hundred Thousand RMB",
          "Signing Date": "January 1, 2024"
        }
      }
    ],
    "submit_time": 1700000000,
    "finish_time": 1700000060
  },
  "usage": {
    "duration": 60,
    "page_count": 5
  },
  "request_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

## Usage Notes

1. **File formats**: Supports PDF, JPG, PNG, BMP, TIFF. Pass the publicly accessible URL via `input.img_url`.
2. **Choosing extraction mode**:
   - When fields are well-defined, use **closed-form mode** (pass `parameters.json_schema`) for the most accurate results.
   - When extraction requirements need flexible description, use **custom prompt mode** (pass `parameters.prompt_cus`).
   - For no specific requirements, use **open-form mode** (pass neither) to automatically identify and extract all recognizable fields.
3. **json_schema format**: The value passed is a **serialized JSON Schema string** (i.e., the result of calling `json.dumps()` on the JSON object), not the JSON object itself.
4. **Result format**: Extraction results are returned via the `output.result` field as a JSON array, where each element corresponds to one input file.
5. **Billing**: Billed by total number of pages; page count is returned via `usage.page_count`.
