# Amend File Category Source: https://docs-docflow.textin.ai/api-reference/amend-file-category /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/amend_category - For regular tasks, modify the file category of the regular task - For document splitting tasks, modify the file type and page numbers of the split files - For multi-image cropping tasks, modify the file type of the cropped files # Delete Tasks Source: https://docs-docflow.textin.ai/api-reference/delete-tasks /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/delete Delete files by conditions. Files matching any condition will be deleted. # Add Single File Category Field Source: https://docs-docflow.textin.ai/api-reference/deprecated/add-single-file-category-field /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/fields/add Add a new field under the specified file category, supports both regular fields and table fields > ⚠️ This endpoint is still available but will no longer be maintained. Please use [Add File Category Fields](/api-reference/file-category/add-file-category-fields) instead. # Update Single File Category Field Source: https://docs-docflow.textin.ai/api-reference/deprecated/update-single-file-category-field /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/fields/update Update the specified file category field, supports both regular fields and table fields > ⚠️ This endpoint is still available but will no longer be maintained. Please use [Update File Category Fields](/api-reference/file-category/update-file-category-fields) instead. # Extract Specific Fields Source: https://docs-docflow.textin.ai/api-reference/extract-specific-fields /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/extract_fields For tasks that have completed extraction, extract additional fields for the task, or re-extract individual existing fields. Returns the complete extraction result of all fields. The return structure is the same as `/api/app-api/sip/platform/v2/file/fetch`. # Delete Category Samples Source: https://docs-docflow.textin.ai/api-reference/file-category-samples/delete-category-samples /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/sample/delete Delete the specified category samples # Download Category Samples (ZIP) Source: https://docs-docflow.textin.ai/api-reference/file-category-samples/download-category-samples-zip /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/sample/batch_download Download multiple sample files of the specified category, packaged as a ZIP file. When sample_ids is not provided, all samples are downloaded. # Get Category Sample List Source: https://docs-docflow.textin.ai/api-reference/file-category-samples/get-category-sample-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/category/sample/list Get the sample list of the specified file category # Upload Category Samples Source: https://docs-docflow.textin.ai/api-reference/file-category-samples/upload-category-samples /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/sample/batch_upload Upload multiple sample files for the specified file category, maximum 20 files # Add File Category Fields Source: https://docs-docflow.textin.ai/api-reference/file-category/add-file-category-fields /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/fields/batch_add Add multiple fields under the specified file category. All-or-nothing semantics — if any field fails validation, the entire batch fails. # Add File Category Tables Source: https://docs-docflow.textin.ai/api-reference/file-category/add-file-category-tables /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/tables/batch_add Add multiple tables under the specified file category (supports nested fields). All-or-nothing semantics. # Create File Category Source: https://docs-docflow.textin.ai/api-reference/file-category/create-file-category /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/create Create a new file category in the specified workspace, requiring at least one sample file and at least one field configuration. Supports one-stop creation: you can pass the `tables` parameter to create tables with nested fields simultaneously. # Delete File Category Source: https://docs-docflow.textin.ai/api-reference/file-category/delete-file-category /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/delete Delete the specified file categories # Delete File Category Fields Source: https://docs-docflow.textin.ai/api-reference/file-category/delete-file-category-fields /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/fields/delete Delete the specified file category fields, supports batch deletion of regular fields and table fields # Delete File Category Tables Source: https://docs-docflow.textin.ai/api-reference/file-category/delete-file-category-tables /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/tables/delete Delete the specified file category tables, supports batch deletion # Get File Category Field List Source: https://docs-docflow.textin.ai/api-reference/file-category/get-file-category-field-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/category/fields/list Get file category field list, including regular fields and tables (with table fields) # Get File Category Table List Source: https://docs-docflow.textin.ai/api-reference/file-category/get-file-category-table-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/category/tables/list Get all tables configured under the specified file category # Get Workspace File Category List Source: https://docs-docflow.textin.ai/api-reference/file-category/get-workspace-file-category-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/category/list Get workspace file category list # Update File Category Source: https://docs-docflow.textin.ai/api-reference/file-category/update-file-category /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/update Update the specified file category information. Note: Setting extract_model will cascade override the extraction model of all fields and tables under this category. # Update File Category Fields Source: https://docs-docflow.textin.ai/api-reference/file-category/update-file-category-fields /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/fields/batch_update Update multiple fields under the specified file category. All-or-nothing semantics. # Update File Category Tables Source: https://docs-docflow.textin.ai/api-reference/file-category/update-file-category-tables /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/category/tables/batch_update Update multiple tables under the specified file category. All-or-nothing semantics. # Generate a short-lived token Source: https://docs-docflow.textin.ai/api-reference/generate-a-short-lived-token /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/auth/token Generate a short-lived token (for iframe scenarios). The token is valid for 1 day. # Get File Processing Result List Source: https://docs-docflow.textin.ai/api-reference/get-file-processing-result-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/file/fetch # Create Review Rule Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/create-review-rule /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule/create Create review rule # Create Review Rule Group Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/create-review-rule-group /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_group/create Create review rule group # Create Review Rule Repository Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/create-review-rule-repository /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_repo/create Create review rule repository # Delete Review Rule Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/delete-review-rule /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule/delete Delete review rule # Delete Review Rule Group Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/delete-review-rule-group /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_group/delete Delete review rule group # Delete Review Rule Repository Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/delete-review-rule-repository /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_repo/delete Delete review rule repository # Delete Review Task Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/delete-review-task /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/task/delete Delete review task # Get Review Rule Repository Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/get-review-rule-repository /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/review/rule_repo/get Get review rule repository # Get Review Rule Repository List Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/get-review-rule-repository-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/review/rule_repo/list Get review rule repository list, including rule groups and rules information under the repository # Get Review Task Result Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/get-review-task-result /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/task/result Get review task result # Retry Review Task Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/retry-review-task /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/task/retry Retry review task # Retry Specific Rule in Review Task Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/retry-specific-rule-in-review-task /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/task/rule/retry Retry a specific rule in the review task. # Submit Review Task Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/submit-review-task /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/task/submit Submit review task # Update Review Rule Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/update-review-rule /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule/update Update review rule # Update Review Rule Group Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/update-review-rule-group /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_group/update Update review rule group # Update Review Rule Repository Source: https://docs-docflow.textin.ai/api-reference/intelligent-review/update-review-rule-repository /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/review/rule_repo/update Update review rule repository # Retry File Processing Source: https://docs-docflow.textin.ai/api-reference/retry-file-processing /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/retry Retry processing a file. # Update File Processing Result Source: https://docs-docflow.textin.ai/api-reference/update-file-processing-result /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/update Update file processing result. Usually used after manual review and proofreading to upload modified key-value pairs, overriding automatically recognized results. # Upload File Source: https://docs-docflow.textin.ai/api-reference/upload-file /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/upload # Upload File Synchronously Source: https://docs-docflow.textin.ai/api-reference/upload-file-synchronously /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/file/upload/sync Upload file and wait for processing to complete, returning processing results directly # Create Workspace Source: https://docs-docflow.textin.ai/api-reference/workspace-management/create-workspace /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/workspace/create Create a new workspace # Delete Workspace Source: https://docs-docflow.textin.ai/api-reference/workspace-management/delete-workspace /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/workspace/delete Delete specified workspace(s) # Get Workspace Details Source: https://docs-docflow.textin.ai/api-reference/workspace-management/get-workspace-details /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/workspace/get Get detailed information of a workspace by workspace ID # Get Workspace List Source: https://docs-docflow.textin.ai/api-reference/workspace-management/get-workspace-list /docflow-global/en/rest-api/openapi.bundle.yaml get /api/app-api/sip/platform/v2/workspace/list Get list of all workspaces for the current user # Update Workspace Source: https://docs-docflow.textin.ai/api-reference/workspace-management/update-workspace /docflow-global/en/rest-api/openapi.bundle.yaml post /api/app-api/sip/platform/v2/workspace/update Update information of a specified workspace # Access Credentials Source: https://docs-docflow.textin.ai/docflow-global/en/00-overview/auth How to obtain and use APIs access credentials ## 01 Access Credential Acquisition ### 1.1 Public Cloud Usage DocFlow uses [TextIn](https://www.textin.ai/) accounts. Please register on [TextIn](https://www.textin.ai/) first, then obtain `x-ti-app-id` and `x-ti-secret-code` on the [TextIn Homepage - Account & Billing - Account & Developer Information](https://www.textin.ai/console/dashboard/setting) page for request authentication. ### 1.2 **Private Cloud Usage** Please contact the technical support personnel you are working with to obtain API call credentials for on-prem deployment. ## 02 Request Authentication DocFlow interface supports two request authentication methods: 1. **Simple Authentication**. This method is simple but has limited security, usually used for quick integration to experience DocFlow processes and effects. 2. **Signature Authentication**. This method is complex but has higher security. It can prevent access credentials from being obtained by man-in-the-middle attacks and tampering with requests. ### 2.1 Simple Authentication Use `x-ti-app-id` and `x-ti-secret-code` as HTTP headers for authentication. Example: ```bash curl theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload" ``` ### 2.2 Signature Authentication Authenticate requests using signatures, requiring 3 HTTP Headers: | Header | Description | | ---------------- | -------------------------------------------------------- | | `x-ti-app-id` | `x-ti-app-id` obtained from TextIn developer information | | `x-ti-timestamp` | Unix Epoch timestamp, in seconds | | `x-ti-signature` | Request signature, calculation method described below | #### Signature Calculation The signature calculation method is: ``` signature = lower(hex(HMAC_SHA256(signing_key, string_to_sign))) ``` Notes: 1. `lower()` is the lowercase letter conversion function 2. `hex()` converts byte array to hexadecimal string 3. `HMAC_SHA256` is a cryptographic hash function, refer to libraries in various development languages 4. `signing_key = HMAC_SHA256(x-ti-secret-code, epoch)`. Where `x-ti-secret-code` is the TextIn developer credential. `epoch` is the Unix Epoch timestamp (seconds). 5. `string_to_sign`, detailed explanation below ##### string\_to\_sign `string_to_sign` is a string concatenated from the following content: ``` "HTTP Method" + "\n" "Request URL" + "\n" "Sorted URL Parameters" + "\n" "sha256(HTTP Request Body)" ``` Notes: 1. HTTP method is uppercase, e.g., `GET`, `POST` 2. Request URL, the path part of the URL (excluding protocol and domain), e.g., `/api/app-api/sip/platform/v2/file/upload` 3. URL parameter sorting sorts all request parameters in ascending order by parameter name dictionary order (ASCII code). Parameter values do not participate in sorting. For example: Suppose the parameters are `workspace_id=12345&batch_num=54321&file_name=invoice.pdf`,\ The sorted result is `batch_num=54321&file_name=invoice.pdf&workspace_id=12345`. Important: 1. Parameter values do not need url encoding when performing signature calculation 2. Parameters are joined with `&`, with no `&` at the end Example: ```python Python expandable {7,8,9,10,11,23,24,25,26,27,28,29,30,31,32,33,34} icon=python lines theme={null} import requests from requests_toolbelt.multipart.encoder import MultipartEncoder import hashlib import hmac import time ti_app_id = "your-app-id" ti_secret_code = "your-app-secret" filename = "file.pdf" filepath = "/path/to/your/file.pdf" params = {"workspace_id":"1871454238893576192","category":"采购订单"} epoch_time = int(time.time()) http_method = "POST" url = "/api/app-api/sip/platform/v2/file/upload" payload = MultipartEncoder( fields={ "file": (filename, open(filepath, "rb"), "application/pdf"), } ) signing_key = hmac.new(ti_secret_code.encode('utf-8'), str(epoch_time).encode('utf-8'), hashlib.sha256).digest() payload_raw = payload.to_string() payload_hash = hashlib.sha256(payload_raw).hexdigest() string_to_sign = f"{http_method}\n{url}\n{'&'.join(f'{k}={v}' for k, v in sorted(params.items()))}\n{payload_hash}" signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest() print(f"epoch_time: {epoch_time}") print(f"http_method: {http_method}") print(f"signing_key: {signing_key}") print(f"payload_hash: {payload_hash}") print(f"string_to_sign: {string_to_sign}") print(f"signature: {signature}") resp = requests.post(url=f"https://docflow.textin.ai{url}", params=params, data=payload_raw, headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-timestamp": str(epoch_time), "x-ti-signature": signature, }) print(resp.text) ``` # Enterprise Multi-Tenant Source: https://docs-docflow.textin.ai/docflow-global/en/00-overview/enterprise_multi_tenant API call instructions for enterprise multi-tenant scenarios ## 01 Enterprise Multi-Tenant Overview When a user belongs to multiple enterprise accounts and needs to operate or access content under a specific enterprise account, it is necessary to add `x-ti-enterprise-id` in the HTTP header to specify the enterprise ID. If the user only belongs to one enterprise, this HTTP header is not required. ## 02 Usage ### 2.1 Multiple Enterprises Scenario When a user belongs to multiple enterprises, it is necessary to add `x-ti-enterprise-id` in the request header to specify the enterprise to operate: ```bash curl theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "x-ti-enterprise-id: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload" ``` ### 2.2 Single Enterprise Scenario If the user only belongs to one enterprise, it is not necessary to add the `x-ti-enterprise-id` header: ```bash curl theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload" ``` ## 03 Get Enterprise ID To obtain the enterprise ID, please refer to the [How to Get Enterprise ID](../100-faq/get_enterprise_id) documentation. # Product Introduction Source: https://docs-docflow.textin.ai/docflow-global/en/00-overview/intro ## 01 Product Overview **Docflow Document Automation Platform** is an AI-powered, enterprise-grade solution from TextIn, a brand of Intsig. Leveraging Intsig's industry-leading document parsing and understanding capabilities, it supports **intelligent collection**, **document parsing**, **document classification**, **information extraction**, and **intelligent review** of various format documents from both domestic and international sources. It provides efficient and accurate document processing solutions for banking credit, financial shared service centers, logistics customs clearance, insurance claims, and other industry enterprises. Through stable and user-friendly APIs,  you can efficiently integrate DocFlow into various business systems to achieve full-process automation from document collection to information extraction, significantly reducing manual input and review costs. 01 En Pn ## 02 Core Value In today’s era of information overload, organizations must process vast volumes of contracts, invoices, reports, application forms, and other documents every day. Traditional manual processing is time-consuming, labor-intensive, and prone to errors. The **DocFlow Document Automation Platform** enables businesses to tackle document management challenges with ease, significantly enhancing efficiency and data accuracy. ### 2.1 **End-to-End Automation** * From file upload to output delivery, the entire workflow is handled intelligently by the system with near-zero manual intervention. This significantly accelerates document processing and reduces operational overhead. ### 2.2 **High-Efficiency & High-Accuracy Extraction** * Processes large volumes of documents within seconds, reducing turnaround time and boosting productivity. * Powered by advanced large-model capabilities, the platform applies document preprocessing techniques — including image quality optimization and intelligent document structure analysis — to maximize recognition accuracy and meet the demands of diverse usage scenarios. ### 2.3 Intelligent Document Splitting * For complex files with multiple categories and multiple documents scanned together, as well as single-page documents with multiple tickets pasted together, automatic document splitting, category separation, and recognition are completed, effectively reducing manual splitting costs and improving document processing results. ### 2.4 Intelligent Document Review * Automated document review is achieved based on document extraction information and review rules. Review results support key review basis echo, effectively improving review result verification efficiency. ### 2.5 Multiple Document Format Compatibility * Supports processing of ultra-long documents up to 1000 pages * Supports file formats including JPEG, JPG, PNG, PDF, OFD, DOC, DOCX, XLS, XLSX, TXT, etc. ### 2.6 On-Demand Customization, Ready to Use * Personalized configuration: Through uploading custom samples and configuring fields, the system intelligently recognizes file categories and completes structured information extraction * Efficient comparison and verification: Supports side-by-side viewing of original files and recognition results to ensure information verification and supplementation, meeting personalized needs of different industries. ### 2.7 Powerful Plugin Integration Capabilities * Accepts input from scanners, email, API endpoints, and other channels. Extracted data can be seamlessly transferred into ERP, RPA, OMS, and other automation systems and business workflows. ## 03 Usage Process **Docflow Document Automation Platform** aims to simplify document management processes and improve enterprise document processing efficiency. Enterprises only need to complete category information configuration to achieve automated document processing workflow. The specific process is as follows: process of using ### 3.1 Workspace Creation After logging in, users can create workspaces tailored to specific business scenarios to manage file categories and documents for those scenarios. ### 3.2 File Category Configuration After completing workspace creation, users can select specific business spaces and configure the following according to business scenario requirements to help the system achieve more accurate automatic classification and field extraction: 1. Create file categories and upload samples 2. Maintain file category classification prompts, field extraction information, etc. Document category configuration ### 3.3 File Upload After completing workspace creation and file category configuration, users can upload documents that need to be processed to the specified workspace through the system platform or API interface. We support automated processing of multiple file format documents, including but not limited to JPEG, JPG, PNG, PDF, OFD, DOC, DOCX, XLS, XLSX, TXT, etc. File upload ### 3.4 Parse Docflow uses [xParse](https://www.textin.ai/market/detail/pdf_to_markdown) as its core document parsing service, which can automatically convert user-uploaded PDF, Word, and common image format documents into structured data containing text, tables, title hierarchies, formulas, handwritten characters, and image information for subsequent automated processing and analysis. ### 3.5 File Splitting & Multi-Image Cropping In practical application scenarios, a document may contain multiple file types. DocFlow provides file splitting and multi-image cropping functions. Users can customize and enable related functions through the system platform or API interface to ensure the accuracy and completeness of document classification and extraction content. For example: 1. Insurance claims scenario: A multi-page PDF may contain identity cards, invoices, bank statements, and other materials at the same time, requiring document page-by-page splitting processing. 2. Financial reimbursement scenario: An A4 paper may have multiple taxi invoices, flight itineraries, and other tickets laid flat, requiring document image cropping processing. Document splitting ### 3.6 Classify DocFlow automatically classifies parsed documents according to workspace file category configuration information, facilitating users to quickly find and manage, as well as subsequent information extraction and review. Users can also obtain classification results through API interfaces for application in other downstream scenarios. Document classification ### 3.7 Extract DocFlow automatically extracts and displays parsed and classified documents according to field information configured in workspace file categories. Users can obtain document extraction results through the system platform or API interface. Information extraction ### 3.8 Intelligent Review Users can create and maintain workspace review rules through the system platform or API interface and initiate review tasks. DocFlow will conduct batch rule review on review task files according to document parsing extraction results and review rules and output review results. Intelligent review ## 04 Try It Now One-stop rapid experience of document automation processing workflow Offers multi-language support and highly configurable API interfaces. Access more detailed product information here. For more partnership information, please contact us. # Quick Start Source: https://docs-docflow.textin.ai/docflow-global/en/00-overview/quickstart Reference examples to quickly integrate Docflow functionality with APIs This document provides examples on how to quickly integrate with the DocFlow workflow via APIs.\ If you have not used DocFlow in the Web UI before, we recommend uploading a file on the [Web page](https://docflow.textin.ai/) first to get a clear idea of how DocFlow works. ## 01 Prerequisites: Obtain Access Credentials ### 1.1 Public Cloud Usage When using the Docflow API, you need to obtain an API Key first.\ Please log in first and go to [TextIn Console - Account & Developer Information](https://www.textin.ai/console/dashboard/setting) to obtain your `x-ti-app-id` and `x-ti-secret-code`. ### 1.2 Private Cloud Usage Please contact the technical support personnel you are working with to obtain API call credentials for private deployment. ## 02 Preparation ### 2.1 Configure Docflow Workspace and Classification First, refer to the [Get Workspace ID](../100-faq/get_workspace_id) and [Configure File Categories](../100-faq/setup_category) documents to complete the configuration and obtain the workspace ID. ## 2.2 Upload Files Example: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F file=@" ``` ```python Python expandable {6,7,8,9} icon=python lines theme={null} import requests import json from requests_toolbelt.multipart.encoder import MultipartEncoder import os ti_app_id = "your-app-id" ti_secret_code = "your-app-secret" workspace_id = "your-workspace-id" filepath = "/your/file/path.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" params = { "workspace_id":workspace_id} # determine filepath is image or pdf if filepath.endswith(".jpg") or filepath.endswith(".jpeg") or filepath.endswith(".png"): mime_type = "image/jpeg" else: mime_type = "application/pdf" payload = MultipartEncoder( fields=[ "file": (os.path.basename(filepath), open(filepath, "rb"), mime_type), ] ) resp = requests.post(url=f"{host}{url}", params=params, data=payload.to_string(), headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) print(resp.text) resp_json = json.loads(resp.text) ``` After executing the above example code with your parameters, you can view the just uploaded file in the corresponding workspace on the Web page. ## 2.3 Retrieve Results Example: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=" ``` ```python Python expandable {4,5,6} icon=python lines theme={null} import requests import json ti_app_id = "your-app-id" ti_secret_code = "your-app-secret" workspace_id = "your-workspace-id" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" params = { "workspace_id":workspace_id} resp = requests.get(url=f"{host}{url}", params=params, data=payload.to_string(), headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) print(resp.text) resp_json = json.loads(resp.text) ``` ## 2.4 Result Parsing The retrieved result is in JSON format containing the processed document results. You can obtain the document parsing, classification, and extraction results by parsing the JSON. The example below shows the extracted document fields in the output. For parsing of other information, refer to the relevant sections of this documentation. ```python Python icon=python lines theme={null} # Continuing from the "Retrieve Results" example code for file in resp_json["result"]["files"]: for item in file["data"]["items"]: print(f"{item["key"]}: {item["value"]}") ``` # Quick Start Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/quickstart Reference examples to quickly integrate document upload functionality with APIs This document demonstrates how to upload files to DocFlow through REST API. For more supported file formats, see [File Format Support](./support_format). Docflow's business processing workflow is asynchronous. The upload interface can upload one or more files to Docflow. Once uploaded successfully, you will receive a batch code (`batch_number`) and several file identifiers (`file_id`) for subsequent business workflow queries and result retrieval. Docflow supports common image formats, PDF, and Office file formats, with multi-page documents supporting up to **1000 pages**. You can refer to the more detailed [File Format Support and Limitations](./support_format) page. ## 01 Upload Single File ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@" ``` ```python Python expandable icon=python lines theme={null} import requests import os from requests_toolbelt.multipart.encoder import MultipartEncoder ti_app_id = "" ti_secret_code = "" workspace_id = "" filepath = "/path/to/your/file.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" payload = MultipartEncoder(fields={ "file": (os.path.basename(filepath), open(filepath, "rb"), mime_type) }) resp = requests.post( url=f"{host}{url}", params={"workspace_id": workspace_id}, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) ``` ### Parameter Description #### Required Parameters * `workspace_id`: Workspace ID. Refer to the [Get Workspace ID](../100-faq/get_workspace_id) document. #### Optional Parameters Can be added to URL query parameters as needed: * `category`: File category (e.g., invoice) * `batch_number`: Batch number, automatically generated by the system when not provided (recommended: use the same batch number for multiple files in the same batch for easier querying) * `auto_verify_vat`: Whether to enable invoice verification, default false * `split_flag`: Whether to perform file splitting, default false (see [File Splitting](../05-split/split) section) * `crop_flag`: Whether to perform multi-image cropping, default false (see [Multi-Image Cropping](../05-split/crop) section) * `target_process`: Target processing type, options are `classify` or `extract`.\ Docflow will perform the complete workflow of parsing -> classification -> extraction by default. When `target_process` is `classify`, the workflow ends at classification to achieve **classification-only** requirements. Example: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/invoice.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&category=invoice" ``` ## 02 Batch Upload When you want to associate multiple files to one batch, you can use batch upload. There are two ways for batch upload: 1. Upload multiple files in one request. This approach is relatively simple, and you can implement batch upload by repeatedly including multiple `file` fields in the same request: Example: ```bash curl icon=terminal theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/1.pdf" \ -F "file=@/path/to/2.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=" ``` ```python Python expandable icon=python lines theme={null} import requests import json from requests_toolbelt.multipart.encoder import MultipartEncoder import time ti_app_id = "your_app_id" ti_secret_code = "your_app_secret" workspace_id = "your_workspace_id" host = "https://docflow.textin.ai" epoch_time = int(time.time()) http_method = "POST" url = "/api/app-api/sip/platform/v2/file/upload" params = { "workspace_id":workspace_id, } payload = MultipartEncoder( fields=[ ("file", ("file1.jpg", open("/path/to/file1.jpg", "rb"), "image/jpeg")), ("file", ("file2.jpg", open(filepath, "rb"), "image/jpeg")), ] ) resp = requests.post(url=f"{host}{url}", params=params, data=payload_raw, headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) print(resp.text) resp_json = json.loads(resp.text) ``` The response will return `result.batch_number` and a list of successfully uploaded `files`. 2. Upload through multiple requests, associating these files through `batch_number`.\ When the total size of multiple files is too large, you can associate multiple files this way. The first request will return a `batch_number`, and subsequent requests reuse this `batch_number` to associate remaining files. Example: ```python Python expandable {35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50} icon=python lines theme={null} import requests import json from requests_toolbelt.multipart.encoder import MultipartEncoder import time import os ti_app_id = "your_app_id" ti_secret_code = "your_app_secret" workspace_id = "your_workspace_id" filepaths = ["/path/to/your/file1.png", "/path/to/your/file2.png"] host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" params = { "workspace_id":workspace_id, } payload = MultipartEncoder( fields=[ ("file", (os.path.basename(filepaths[0]), open(filepaths[0], "rb"), "image/png")), ] ) resp = requests.post(url=f"{host}{url}", params=params, data=payload.to_string(), headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) print(resp.text) resp_json = json.loads(resp.text) # get and reuse `batch_number` batch_number = resp_json["result"]["batch_number"] params["batch_number"] = batch_number payload = MultipartEncoder( fields=[ ("file", (os.path.basename(filepaths[1]), open(filepaths[1], "rb"), "image/png")), ] ) resp = requests.post(url=f"{host}{url}", params=params, data=payload.to_string(), headers={"Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) print(resp.text) resp_json = json.loads(resp.text) ``` ## 03 Query Processing Results by Batch Number After upload is complete, you can use `batch_number` to query processing results for that batch: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&batch_number=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" batch_number = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "batch_number": batch_number}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f["id"], f.get("name"), f.get("recognition_status"), f.get("category")) ``` # Response JSON Structure Description Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/response Docflow file upload is an asynchronous interface.\ When the interface call is successful, it returns result identifiers (`batch_number` and `file ID`) for subsequent result retrieval. After a successful upload interface request, the response will be returned in JSON format according to the following structure: ```json expandable theme={null} { "code":200, "msg":"成功", "result":{ "batch_number":"1955840540571376304", "files":[ { "id":"1955840505753140508", "task_id":"1981692246135111680", "name":"企业信用报告.pdf", "format":"pdf" } ] } } ``` ## Important Field Description * `batch_number`: File batch number. Can be associated with multiple files within the same batch. * `files[].id`: File ID for this upload. * `files[].task_id`: Task ID for identifying file processing tasks. Both `batch_number`, `files[].id` and `files[].task_id` can be used as query conditions for subsequent result retrieval. # File Format Support Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/support_format DocFlow supports the following file formats: * **Documents:** PDF/OFD/DOC/DOCX/TXT * **Spreadsheets:** XLS/XLSX * **Images:** JPEG/JPG/PNG/TIFF/TIF ## File Limitations Each uploaded file must meet the following requirements: 1. File size: **no more than 100 MB** 2. Page count: **no more than 1,000 pages** 3. Number of extraction fields: **no more than 100** # Task Status Query Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/task_status Learn how to query task status, failure reasons, task duration, and other information This article explains how to query DocFlow task processing status, failure reasons, and duration information. Task status helps you understand file processing progress and results. DocFlow uses asynchronous processing mode. After file upload, files enter the processing queue. You can query task status through multiple methods to understand processing progress, failure reasons, and task duration information. ## Task Status Description Task status in DocFlow is represented by the `recognition_status` field. The specific statuses are as follows: | Status Value | Status Name | Description | | ------------ | ----------------------- | ---------------------------------------------------- | | 0 | Pending Recognition | File uploaded, waiting to start processing | | 1 | Recognition Success | File processing completed successfully | | 2 | Recognition Failed | File processing failed, failure reason can be viewed | | 3 | Classifying | File classification processing in progress | | 4 | Extracting | Field extraction processing in progress | | 5 | Preparing | Task preparation stage | | 6 | File Splitting | File splitting processing in progress | | 7 | Image Cropping | Multi-image cropping processing in progress | | 10 | Classification Complete | Completion status for classification-only mode | | 20 | Parsing | Document parsing processing in progress | ## Query Task Status ### Query by Batch Number Use `batch_number` to query task status for the entire batch: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&batch_number=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" batch_number = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "batch_number": batch_number}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}") print(f"File Name: {f.get('name')}") print(f"Task Status: {f.get('recognition_status')}") print(f"File Category: {f.get('category')}") if f.get('recognition_status') == 2: print(f"Failure Reason: {f.get('failure_causes')}") print("---") ``` ### Query by File ID Use `file_id` to query task status for a specific file: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" file_id = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "file_id": file_id}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() file_info = data.get("result", {}).get("files", [{}])[0] print(f"File ID: {file_info.get('id')}") print(f"File Name: {file_info.get('name')}") print(f"Task Status: {file_info.get('recognition_status')}") print(f"File Category: {file_info.get('category')}") if file_info.get('recognition_status') == 2: print(f"Failure Reason: {file_info.get('failure_causes')}") ``` ### Query by Task ID Use `task_id` to query status for a specific task: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&task_id=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" task_id = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "task_id": task_id}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() file_info = data.get("result", {}).get("files", [{}])[0] print(f"Task ID: {file_info.get('task_id')}") print(f"File ID: {file_info.get('id')}") print(f"File Name: {file_info.get('name')}") print(f"Task Status: {file_info.get('recognition_status')}") print(f"File Category: {file_info.get('category')}") if file_info.get('recognition_status') == 2: print(f"Failure Reason: {file_info.get('failure_causes')}") ``` ## Query Task Duration After task processing is completed, you can view task duration through the `duration_ms` field (unit: milliseconds): ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" batch_number = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "batch_number": batch_number}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}") print(f"File Name: {f.get('name')}") print(f"Task Status: {f.get('recognition_status')}") # View task duration if f.get('duration_ms'): duration_seconds = f['duration_ms'] / 1000 print(f"Task Duration: {duration_seconds:.2f} seconds") print("---") ``` ## Failure Reason Analysis When task status is `2` (Recognition Failed), you can view specific failure reasons through the `failure_causes` field: ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" batch_number = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "batch_number": batch_number}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): if f.get('recognition_status') == 2: print(f"File ID: {f['id']}") print(f"File Name: {f.get('name')}") print(f"Failure Reason: {f.get('failure_causes')}") print("---") ``` ## Status Filter Query You can filter tasks by specific status using the `recognition_status` parameter: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&recognition_status=2" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" # Query all failed tasks resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "recognition_status": 2}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() print(f"Failed Task Count: {len(data.get('result', {}).get('files', []))}") for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}") print(f"File Name: {f.get('name')}") print(f"Failure Reason: {f.get('failure_causes')}") print("---") ``` ## Response Example Example response for querying task status: ```json expandable theme={null} { "code": 200, "msg": "Success", "result": { "files": [ { "id": "1955840505753140508", "task_id": "1981692246135111680", "name": "Corporate Credit Report.pdf", "format": "pdf", "recognition_status": 1, "verification_status": 0, "category": "credit_report", "duration_ms": 15000, "failure_causes": null }, { "id": "1955840505753140509", "task_id": "1981692246135111681", "name": "Invoice.pdf", "format": "pdf", "recognition_status": 2, "verification_status": 0, "category": "invoice", "duration_ms": 8000, "failure_causes": "Unsupported file format" } ] } } ``` # Upload by URLs Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/upload_by_urls Upload documents to DocFlow using file URLs This guide demonstrates how to upload documents to DocFlow using file URLs via REST API.\ Compared to direct file upload, URL upload is more suitable for processing remote files or batch processing scenarios. DocFlow supports uploading documents via file URLs without requiring local file storage. This approach is particularly suitable for: * Processing files on remote servers * Batch processing multiple file URLs * Reducing local storage and network transmission overhead ## 01 Single File URL Upload Submit file URL list using `application/json` format: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "urls": ["https://example.com/document.pdf"] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" file_url = "https://example.com/document.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" payload = { "urls": [file_url] } resp = requests.post( url=f"{host}{url}", params={"workspace_id": workspace_id}, json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) ``` ## 02 Batch URL Upload A single request can upload multiple file URLs, supporting up to **10 files**: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "urls": [ "https://example.com/invoice1.pdf", "https://example.com/invoice2.pdf", "https://example.com/contract.docx" ] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&batch_number=202412190001" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" # Batch upload multiple file URLs file_urls = [ "https://example.com/invoice1.pdf", "https://example.com/invoice2.pdf", "https://example.com/contract.docx" ] payload = { "urls": file_urls } resp = requests.post( url=f"{host}{url}", params={ "workspace_id": workspace_id, "batch_number": "202412190001", "category": "invoice" }, json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) result = resp.json() print(f"Batch number: {result['result']['batch_number']}") for file_info in result['result']['files']: print(f"File ID: {file_info['id']}, File name: {file_info['name']}") ``` ## 03 Parameter Description ### Required Parameters * `workspace_id`: Workspace ID. Please refer to the [Get Workspace ID](../100-faq/get_workspace_id) documentation. ### Request Body Parameters * `urls`: File URL list * Type: String array * Limit: Maximum 10 URLs per request * Format: Must be valid URLs starting with `http://` or `https://` * File size: Each file maximum 100MB ### Optional Parameters Can be added in URL query parameters as needed: * `category`: File category (e.g., invoice) * `batch_number`: Batch number, auto-generated if not provided * `auto_verify_vat`: Whether to enable invoice verification, default false * `split_flag`: Whether to perform file splitting, default false (see [File Splitting](../05-split/split) chapter) * `crop_flag`: Whether to perform multi-image cropping, default false (see [Multi-image Cropping](../05-split/crop) chapter) * `target_process`: Target processing type, optional `classify` or `extract` ## 04 URL Requirements ### Supported URL Formats * Must start with `http://` or `https://` * URL must be publicly accessible (no authentication required) * Server must support HTTP GET requests ### File Requirements * File format: Supports all formats listed in [File Format Support](./support_format) * File size: Single file not exceeding 100MB * File pages: Multi-page documents not exceeding 1000 pages ### Example URLs ```bash theme={null} # Valid URL examples https://example.com/document.pdf https://cdn.example.com/files/invoice.pdf http://192.168.1.100/shared/contract.docx # Invalid URL examples ftp://example.com/file.pdf # FTP protocol not supported file:///local/path/document.pdf # Local file paths not supported https://example.com/protected.pdf # URLs requiring authentication ``` ## 05 Response Format The response format after successful URL upload is the same as regular file upload: ```json expandable theme={null} { "code": 200, "msg": "Success", "result": { "batch_number": "202412190001", "files": [ { "id": "1955840505753140508", "name": "document.pdf", "format": "pdf" }, { "id": "1955840505753140509", "name": "invoice.pdf", "format": "pdf" } ] } } ``` ## 06 Query Processing Results After upload completion, use the returned `batch_number` to query processing results: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&batch_number=" ``` ```python Python expandable icon=python lines theme={null} import requests import json ti_app_id = "" ti_secret_code = "" workspace_id = "" batch_number = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id, "batch_number": batch_number}, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}, File name: {f.get('name')}, Status: {f.get('recognition_status')}") ``` # Synchronous Upload Source: https://docs-docflow.textin.ai/docflow-global/en/01-upload/upload_sync Upload file synchronously and wait for processing to complete, returning processing results directly This document demonstrates how to upload files to DocFlow through REST API using the synchronous upload interface.\ The synchronous upload interface waits for file processing to complete before returning results, suitable for scenarios that require immediate access to processing results. DocFlow provides a synchronous upload interface `/api/app-api/sip/platform/v2/file/upload/sync`. The difference between this interface and the regular upload interface `/api/app-api/sip/platform/v2/file/upload` is: * **Regular Upload Interface**: Returns immediately after uploading the file, requires subsequent querying of processing results through the `/file/fetch` interface * **Synchronous Upload Interface**: Waits for processing to complete after uploading the file, directly returns complete processing results without additional queries The synchronous upload interface waits for file processing to complete. Processing time depends on file size and complexity.\ For large files or complex documents, it may require a longer waiting time. It is recommended to set an appropriate timeout. ## 01 Upload Single File Synchronously Upload file using `multipart/form-data` format: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/your/file.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload/sync?workspace_id=" ``` ```python Python expandable icon=python lines theme={null} import requests import os from requests_toolbelt.multipart.encoder import MultipartEncoder ti_app_id = "" ti_secret_code = "" workspace_id = "" filepath = "/path/to/your/file.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload/sync" mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" payload = MultipartEncoder(fields={ "file": (os.path.basename(filepath), open(filepath, "rb"), mime_type) }) resp = requests.post( url=f"{host}{url}", params={"workspace_id": workspace_id}, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=300, # Synchronous interface requires longer timeout ) print(resp.status_code, resp.text) result = resp.json() if result.get("code") == 200: files = result.get("result", {}).get("files", []) for f in files: print(f"File ID: {f['id']}, File Name: {f.get('name')}, Status: {f.get('recognition_status')}") # Can directly access processing results if f.get("data"): print(f"Extracted fields: {f['data'].get('fields', [])}") ``` ## 02 Upload Multiple Files Synchronously You can upload multiple files in one request. The system will wait for all files to be processed before returning: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/1.pdf" \ -F "file=@/path/to/2.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload/sync?workspace_id=&batch_number=202412190001" ``` ```python Python expandable icon=python lines theme={null} import requests import os from requests_toolbelt.multipart.encoder import MultipartEncoder ti_app_id = "" ti_secret_code = "" workspace_id = "" filepaths = ["/path/to/file1.pdf", "/path/to/file2.pdf"] host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload/sync" fields = [] for filepath in filepaths: mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" fields.append(("file", (os.path.basename(filepath), open(filepath, "rb"), mime_type))) payload = MultipartEncoder(fields=fields) resp = requests.post( url=f"{host}{url}", params={ "workspace_id": workspace_id, "batch_number": "202412190001", "category": "invoice" }, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=300, ) print(resp.status_code, resp.text) result = resp.json() if result.get("code") == 200: files = result.get("result", {}).get("files", []) print(f"Processing completed, {len(files)} files") for f in files: print(f"File: {f.get('name')}, Status: {f.get('recognition_status')}") ``` ## 03 Upload via URL Synchronously The synchronous upload interface also supports uploading via file URLs: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "urls": ["https://example.com/document.pdf"] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload/sync?workspace_id=" ``` ```python Python expandable icon=python lines theme={null} import requests ti_app_id = "" ti_secret_code = "" workspace_id = "" file_url = "https://example.com/document.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload/sync" payload = { "urls": [file_url] } resp = requests.post( url=f"{host}{url}", params={"workspace_id": workspace_id}, json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=300, ) print(resp.status_code, resp.text) result = resp.json() if result.get("code") == 200: files = result.get("result", {}).get("files", []) for f in files: print(f"File ID: {f['id']}, Processing Status: {f.get('recognition_status')}") # Directly access processing results if f.get("data") and f.get("data").get("fields"): for field in f["data"]["fields"]: print(f" {field.get('key')}: {field.get('value')}") ``` ## 04 Parameter Description The parameters of the synchronous upload interface are exactly the same as the regular upload interface: ### Required Parameters * `workspace_id`: Workspace ID. You can refer to the [Get Workspace ID](../100-faq/get_workspace_id) documentation. ### Optional Parameters Can be added in URL query parameters as needed: * `category`: File category (e.g., invoice) * `batch_number`: Batch number, automatically generated by the system if not provided * `auto_verify_vat`: Whether to enable invoice verification, default false * `split_flag`: Whether to perform file splitting, default false (see [File Splitting](../05-split/split) section) * `crop_flag`: Whether to perform multi-image cropping, default false (see [Multi-image Cropping](../05-split/crop) section) * `target_process`: Target processing type, optional `classify` or `extract`.\ Docflow will perform the complete process of parsing->classification->extraction by default. When `target_process` is `classify`, the process ends after classification ### Request Body Parameters Supports two methods: 1. **File Upload**: Use `multipart/form-data` format, field name is `file` (can be repeated multiple times) 2. **URL Upload**: Use `application/json` format, contains `urls` array (up to 10 URLs) ## 05 Response Format The response format returned by the synchronous upload interface is the same as the `/file/fetch` interface, containing complete processing results: ```json expandable theme={null} { "code": 200, "msg": "Success", "result": { "total": 1, "page": 1, "page_size": 20, "files": [ { "id": "1955840505753140508", "task_id": "1955840505753140509", "task_type": 1, "batch_number": "202412190001", "name": "invoice.pdf", "format": "pdf", "recognition_status": 1, "verification_status": 0, "category": "invoice", "pages": [ { "page": 0, "angle": 0, "width": 1024, "height": 1448, "dpi": 144 } ], "data": { "fields": [ { "key": "Invoice Code", "identifier": "Invoice Code Identifier", "value": "3100231130", "position": [ { "page": 0, "vertices": [100, 200, 300, 200, 300, 250, 100, 250] } ] }, { "key": "Invoice Number", "identifier": "Invoice Number Identifier", "value": "28737000", "position": [ { "page": 0, "vertices": [350, 200, 500, 200, 500, 250, 350, 250] } ] } ], "items": [], "tables": [], "stamps": [], "handwritings": [] }, "duration_ms": 5000 } ] } } ``` Key fields in the response: * `result.files[]`: File list, each file contains complete processing results * `result.files[].data.fields[]`: Extracted field list * `result.files[].data.items[]`: Table data list * `result.files[].data.tables[]`: All table data list * `result.files[].data.stamps[]`: Stamp information * `result.files[].data.handwritings[]`: Handwriting information * `result.files[].recognition_status`: Recognition status (1 indicates success) * `result.files[].duration_ms`: Processing time (milliseconds) ## 06 Use Cases ### Scenarios Suitable for Synchronous Upload * Scenarios that require immediate access to processing results * Single file or small number of files processing * File processing time is short (usually seconds to tens of seconds) * Simplify code logic, avoid polling queries ### Scenarios Not Suitable for Synchronous Upload * Batch processing of large numbers of files * File processing time is long (exceeding 1 minute) * Scenarios requiring asynchronous processing * Unstable network or scenarios requiring resumable uploads For scenarios not suitable for synchronous upload, it is recommended to use the regular upload interface `/file/upload` with the `/file/fetch` query interface to implement an asynchronous processing workflow. ## 07 Notes 1. **Timeout Settings**: The synchronous upload interface needs to wait for processing to complete. It is recommended to set a longer timeout (at least 300 seconds) 2. **Processing Time**: Processing time depends on file size, number of pages, and complexity. Large files may require longer processing time 3. **Error Handling**: If processing fails, the response will contain error information. `recognition_status` of 2 indicates failure 4. **Batch Processing**: When uploading multiple files at once, it will wait for all files to be processed, which may result in longer total processing time 5. **Network Stability**: Since a long connection needs to be maintained, ensure network connection stability # Quickstart Source: https://docs-docflow.textin.ai/docflow-global/en/02-workspace/quickstart Quick API integration of workspace management features A Workspace is the basic unit in DocFlow for organizing and isolating document processing tasks. Each workspace can contain file categories, review rule repositories, and other resources, facilitating multi-tenant or multi-project management. This guide introduces how to use workspace-related APIs: create, list, get, update, and delete. ## Create Workspace Create a new workspace: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "name": "My Workspace", "description": "This is a workspace for processing invoices", "enterprise_id": 12345, "auth_scope": 1 }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/workspace/create" ``` ```python Python icon=python expandable lines theme={null} import requests ti_app_id = "" ti_secret_code = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/workspace/create" payload = { "name": "My Workspace", "description": "This is a workspace for processing invoices", "enterprise_id": 12345, "auth_scope": 1 # 0: Private, 1: Enterprise-wide } resp = requests.post( url=f"{host}{url}", json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=30, ) result = resp.json() if result.get("code") == 200: workspace_id = result.get("result", {}).get("workspace_id") print(f"Workspace created successfully, ID: {workspace_id}") else: print(f"Creation failed: {result.get('msg')}") ``` **Request Parameters:** * `name` (required): Workspace name, max length 50 * `description` (optional): Workspace description, max length 200 * `enterprise_id` (required): Enterprise organization ID * `auth_scope` (required): Collaboration scope, 0: Private, 1: Enterprise-wide **Response Example:** ```json theme={null} { "code": 200, "msg": "success", "result": { "workspace_id": "1234567890" } } ``` ## List Workspaces Get all workspaces for the current user: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/workspace/list?enterprise_id=12345&page=1&page_size=20" ``` ```python Python icon=python expandable lines theme={null} import requests ti_app_id = "" ti_secret_code = "" enterprise_id = 12345 host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/workspace/list" resp = requests.get( url=f"{host}{url}", params={ "enterprise_id": enterprise_id, "page": 1, "page_size": 20 }, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=30, ) result = resp.json() if result.get("code") == 200: workspaces = result.get("result", {}).get("workspaces", []) total = result.get("result", {}).get("total", 0) print(f"Found {total} workspaces") for workspace in workspaces: print(f"Workspace ID: {workspace.get('workspace_id')}, Name: {workspace.get('name')}") else: print(f"Retrieval failed: {result.get('msg')}") ``` **Request Parameters:** * `enterprise_id` (required): Enterprise ID * `page` (optional): Page number, default is 1 * `page_size` (optional): Items per page, default is 20 **Response Example:** ```json theme={null} { "code": 200, "msg": "success", "result": { "total": 10, "page": 1, "page_size": 20, "workspaces": [ { "workspace_id": "1234567890", "name": "My Workspace", "description": "This is a workspace for processing invoices", "auth_scope": 1, "manage_account_id": "admin_123456", "manage_account_name": "John Doe", "callback_url": "https://example.com/callback", "callback_retry_time": 3 } ] } } ``` ## Get Workspace Details Get detailed information about a workspace by its ID: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/workspace/get?workspace_id=1234567890" ``` ```python Python icon=python expandable lines theme={null} import requests ti_app_id = "" ti_secret_code = "" workspace_id = "1234567890" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/workspace/get" resp = requests.get( url=f"{host}{url}", params={"workspace_id": workspace_id}, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=30, ) result = resp.json() if result.get("code") == 200: workspace = result.get("result", {}) print(f"Workspace name: {workspace.get('name')}") print(f"Description: {workspace.get('description')}") print(f"Administrator: {workspace.get('manage_account_name')}") else: print(f"Retrieval failed: {result.get('msg')}") ``` **Request Parameters:** * `workspace_id` (required): Workspace ID ## Update Workspace Update information for a specified workspace: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "workspace_id": "1234567890", "name": "Updated Workspace Name", "description": "Updated description", "auth_scope": 1, "callback_url": "https://example.com/callback", "callback_retry_time": 3 }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/workspace/update" ``` ```python Python icon=python expandable lines theme={null} import requests ti_app_id = "" ti_secret_code = "" workspace_id = "1234567890" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/workspace/update" payload = { "workspace_id": workspace_id, "name": "Updated Workspace Name", "description": "Updated description", "auth_scope": 1, "callback_url": "https://example.com/callback", "callback_retry_time": 3 } resp = requests.post( url=f"{host}{url}", json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=30, ) result = resp.json() if result.get("code") == 200: print("Workspace updated successfully") else: print(f"Update failed: {result.get('msg')}") ``` **Request Parameters:** * `workspace_id` (required): Workspace ID * `name` (required): Workspace name, max length 50 * `description` (optional): Workspace description, max length 200 * `auth_scope` (required): Collaboration scope, 0: Private, 1: Enterprise-wide * `callback_url` (optional): Callback URL * `callback_retry_time` (optional): Number of callback retries, range 0-3 ## Delete Workspace Delete specified workspace(s) (supports batch deletion): ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "workspace_ids": ["1234567890", "0987654321"] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/workspace/delete" ``` ```python Python icon=python expandable lines theme={null} import requests ti_app_id = "" ti_secret_code = "" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/workspace/delete" payload = { "workspace_ids": ["1234567890", "0987654321"] } resp = requests.post( url=f"{host}{url}", json=payload, headers={ "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=30, ) result = resp.json() if result.get("code") == 200: print("Workspace deleted successfully") else: print(f"Deletion failed: {result.get('msg')}") ``` **Request Parameters:** * `workspace_ids` (required): Array of workspace IDs to delete Deleting a workspace will also delete all resources under it (including file categories, review rule repositories, etc.). Please proceed with caution. ## Next Steps * Learn [Category Management](../10-category-management/quickstart) - Create and manage file categories in workspace * Learn [Review Rule Management](../07-review/rule_management) - Create review rule repositories in workspace # Coordinate System Source: https://docs-docflow.textin.ai/docflow-global/en/03-parse/coordinate Coordinates are an array containing 8 integers, in the format `[x1, y1, x2, y2, x3, y3, x4, y4]` Representing the coordinates of four vertices of a quadrilateral, arranged clockwise. Namely: * Top-left: (x1, y1) * Top-right: (x2, y2) * Bottom-right: (x3, y3) * Bottom-left: (x4, y4) Coordinate values are absolute pixel values. The coordinate system is as follows: ``` Image coordinate system (origin at top-left corner) ┌────────────width───────────> x │(0,0) │ │ │ (x1,y1) ────────── (x2,y2) │ │ │ height Text area │ │ │ │ (x4,y4) ────────── (x3,y3) │ v y ``` # Quick Start Source: https://docs-docflow.textin.ai/docflow-global/en/03-parse/quickstart Reference examples to quickly integrate document parsing functionality with APIs Docflow uses [xParse](https://www.textin.ai/market/detail/pdf_to_markdown) as its core document parsing service, which can accurately convert PDF, Word, and common image format documents into structured data containing text, tables, title hierarchies, formulas, handwritten characters, and image information for subsequent automated processing and analysis. In application scenarios such as knowledge base construction and unstructured document image processing, powerful document parsing capabilities can meet most requirements. The document parsing results returned by Docflow's result retrieval interface are heavily trimmed from xParse results, retaining only basic text blocks and position information for page text position visualization rendering. This document uses [this sample document](https://dllf.intsig.net/download/2025/Solution/20250829/simple.pdf) as an example to explain how to obtain document parsing results. ## Prerequisites According to the [Document Upload](../01-upload/quickstart#upload-single-file) instructions, upload a file and obtain the returned file ID. File processing takes time. You need to wait several seconds after uploading before you can retrieve processing results. ## Get Document Parsing Results Document parsing results are large in size and are not returned by default.\ When calling the result retrieval interface, add the URL parameter `with_document=true` to return document parsing results. Example: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=&with_document=true" ``` ```python Python expandable {13} icon=python lines theme={null} import requests import json ti_app_id = "your_app_id" ti_secret_code = "your_app_secret" workspace_id = "your_workspace_id" file_id = "your_file_id" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" params = { "workspace_id":workspace_id, "with_document": "true", "file_id":file_id } resp = requests.get(url=f"{host}{url}", params=params, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) resp_json = json.loads(resp.text) for file in resp_json["result"]["files"]: print(f"file {file["name"]} parse result: {file["document"]}") ``` ## Response JSON Structure Description The document parsing structure is in `result.files[].document`, with the following example (excerpt): ```json expandable theme={null} "document":{ "pages":[ { "angle":0, "width":1191, "height":794, "lines":[ { "text":"电子发票(普通发票)", "position":[ 389, 45, 767, 45, 767, 87, 389, 87 ], "charPositions":[] } ] } ] } ``` Field descriptions are as follows: * `document`: Document parsing result object * `pages`: Array of parsing results for each page of the document * `angle`: Rotation angle of the document page * `width`: Width of the document page * `height`: Height of the document page * `lines`: Results for each text line in the document * `text`: Text content * `position`: Text coordinates * `charPositions`: Coordinates of each character in the text The meaning of `position` can be referenced in the [Coordinate System Description](./coordinate). # Parsing Result Visualization Source: https://docs-docflow.textin.ai/docflow-global/en/03-parse/visualization How to obtain precise coordinates from parsing results and display them on the interface This document continues from the [previous section](./quickstart), explaining how to process parsing results after obtaining them and draw text boxes at corresponding positions on the original file. This document uses [this sample document](https://dllf.intsig.net/download/2025/Solution/20250829/simple.pdf) as an example to explain how to draw text boxes on the original file image. Please install dependencies before running the example code: `pip install PyMuPDF pillow requests` ## Example Code ```python Python expandable icon=python lines theme={null} import requests import json import os import fitz # PyMuPDF from PIL import Image, ImageDraw ti_app_id = "your_app_id" ti_secret_code = "your_app_secret" workspace_id = "your_workspace_id" file_id = "your_file_id" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/fetch" params = { "workspace_id":workspace_id, "with_document": "true", "file_id":file_id } resp = requests.get(url=f"{host}{url}", params=params, headers={"x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }) resp_json = json.loads(resp.text) def extract_pages_from_docflow(document): pages_out = [] for page in document.get("pages", []): pages_out.append({ "width": page.get("width", 0), "height": page.get("height", 0), "angle": page.get("angle", 0), "lines": page.get("lines", []) }) return pages_out def pdf_to_images(pdf_path, output_dir="./docflow_pages", dpi=144): os.makedirs(output_dir, exist_ok=True) doc = fitz.open(pdf_path) zoom = dpi / 72.0 mat = fitz.Matrix(zoom, zoom) image_paths = [] for i, page in enumerate(doc): pix = page.get_pixmap(matrix=mat) img_path = os.path.join(output_dir, f"page_{i+1}.png") pix.save(img_path) image_paths.append(img_path) doc.close() return image_paths def draw_quads_on_image(image_path, quads, page_width, page_height, color=(26,102,255), line_width=2): image = Image.open(image_path).convert("RGB") draw = ImageDraw.Draw(image) img_w, img_h = image.size scale_x = img_w / page_width if page_width else 1 scale_y = img_h / page_height if page_height else 1 for q in quads: pos = q.get("position") if pos and len(pos) == 8: points = [ (pos[0]*scale_x, pos[1]*scale_y), (pos[2]*scale_x, pos[3]*scale_y), (pos[4]*scale_x, pos[5]*scale_y), (pos[6]*scale_x, pos[7]*scale_y), (pos[0]*scale_x, pos[1]*scale_y) ] draw.line(points, fill=color, width=line_width) out_path = image_path.replace('.png', '_boxed.png') image.save(out_path) return out_path # Select the original PDF to visualize (same file as parsed) pdf_path = "./simple.pdf" # Please replace with your original PDF path # Extract coordinate data files = resp_json.get("result", {}).get("files", []) if not files: raise RuntimeError("No file parsing results obtained") document = files[0].get("document", {}) pages = extract_pages_from_docflow(document) # Convert to images and draw coordinates image_paths = pdf_to_images(pdf_path, output_dir="./docflow_pages") annotated = [] for i, page in enumerate(pages): if i >= len(image_paths): break out_path = draw_quads_on_image( image_paths[i], page["lines"], page["width"], page["height"] ) annotated.append(out_path) print("Annotated images output:", annotated) ``` In the output directory, you can see the rendering effect of text boxes: visualization ## Example Code Logic * **Get parsing results**: Call the result retrieval interface with `with_document=true` enabled to get `result.files[].document`. * **Extract pages and coordinates**: Read `width/height/angle` and `lines[]` from `document.pages[]`; each `line.position` is `[x1,y1,x2,y2,x3,y3,x4,y4]` clockwise four-point coordinates. * **Prepare base image**: Use the same file as parsing to generate page images. If converting images yourself, remember to record the rendered `img_width/img_height`. * **Coordinate scaling**: Calculate `scale_x = img_width / page.width`, `scale_y = img_height / page.height`, and scale the returned coordinates proportionally to the base image pixel coordinate system. * **Draw visualization**: Draw the scaled four points as closed polylines (or filled polygons) on the corresponding page image line by line, with configurable line width, color, and transparency. * **Output and display**: Save annotated images, or overlay rendering in frontend canvas/SVG/Canvas; ensure page-by-page correspondence. * **Optional enhancements**: * Handle `angle` rotation: If the base image is not rotated correctly, coordinate rotation correction based on `page.angle` is needed. * Multi-type coloring: Different element types can use different colors/legends; if there are table, image, and other types, they can be differentiated as needed. * Character-level highlighting: If `charPositions` is returned, scale each character coordinate proportionally and draw for more refined echo effects. * Performance optimization: Batch drawing, resolution trade-offs, on-demand page rendering to avoid processing too many pages at once causing lag. * Robustness: Null value checking, coordinate boundary clipping, fault tolerance for network/parsing exceptions. The above process is language-agnostic. When implementing in other languages, you only need to replace the libraries and APIs for: HTTP requests, JSON parsing, image drawing, and coordinate scaling. # Amend File Category Source: https://docs-docflow.textin.ai/docflow-global/en/04-classify/amend_category For normal tasks, use the amend category API to modify file categories ## Overview For completed normal tasks, if the file category is incorrect, you can use the **amend category** API to modify the file category. After modification, the system will reprocess the data using the new category. Only normal tasks support category modification. File split tasks and multi-image crop tasks require using corresponding parameters for modification. After modifying the file category, the system will automatically re-extract using the fields configured for the new category, and the extraction results will change. ## Use Cases 1. **Category Error Correction**: Automatic classification results are incorrect and need manual correction 2. **Category Adjustment**: Business requirements change and files need to be reclassified ## API Endpoint **Endpoint**: `POST /api/app-api/sip/platform/v2/file/amend_category` ## Request Parameters | Parameter | Type | Required | Description | | -------------- | ------ | -------- | ----------------- | | `workspace_id` | string | Yes | Workspace ID | | `task_id` | string | Yes | Task ID | | `category` | string | Yes | New file category | ### Parameter Description * `task_id`: Can be obtained through the `file/fetch` API * `category`: New file category name, must be a file category already configured in the DocFlow workspace ## Example Code ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "workspace_id": "1234567890", "task_id": "1234567890", "category": "Electronic Invoice (Regular)" }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" ``` ```python Python icon=python expandable theme={null} import requests import json def amend_category(workspace_id, task_id, category, app_id, secret_code): """ Amend file category for normal tasks """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "category": category } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example if __name__ == "__main__": WORKSPACE_ID = "1234567890" TASK_ID = "1234567890" CATEGORY = "Electronic Invoice (Regular)" APP_ID = "" SECRET_CODE = "" result = amend_category(WORKSPACE_ID, TASK_ID, CATEGORY, APP_ID, SECRET_CODE) print(json.dumps(result, indent=2, ensure_ascii=False)) ``` ## Get Task ID Before modifying the file category, you need to obtain the task's `task_id`. You can query it through the `file/fetch` API: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python icon=python expandable theme={null} import requests def get_task_id(workspace_id, file_id, app_id, secret_code): """ Get the task ID for a file """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = { "workspace_id": workspace_id, "file_id": file_id } response = requests.get(url, headers=headers, params=params) data = response.json() # Extract task_id from the response files = data.get("result", {}).get("files", []) if files: return files[0].get("task_id") return None # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" APP_ID = "" SECRET_CODE = "" task_id = get_task_id(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) print(f"Task ID: {task_id}") ``` ## Response After successfully modifying the file category, the API returns a success response: ```json expandable theme={null} { "code": 200, "message": "success" } ``` ## Complete Example The following is a complete example showing how to query file information, get the task ID, and then modify the file category: ```python Python icon=python expandable theme={null} import requests import json def get_file_info(workspace_id, file_id, app_id, secret_code): """Get file information""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = {"workspace_id": workspace_id, "file_id": file_id} response = requests.get(url, headers=headers, params=params) return response.json() def amend_category(workspace_id, task_id, category, app_id, secret_code): """Amend file category""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "category": category } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" NEW_CATEGORY = "Electronic Invoice (Regular)" APP_ID = "" SECRET_CODE = "" # 1. Get file information and task ID file_info = get_file_info(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) files = file_info.get("result", {}).get("files", []) if files: file_data = files[0] task_id = file_data.get("task_id") current_category = file_data.get("category") print(f"Current file category: {current_category}") print(f"Task ID: {task_id}") # 2. Amend file category result = amend_category(WORKSPACE_ID, task_id, NEW_CATEGORY, APP_ID, SECRET_CODE) print(f"Amendment result: {json.dumps(result, indent=2, ensure_ascii=False)}") ``` ## Notes 1. **Task Type Restriction**: Only normal tasks (non-split tasks, non-multi-image crop tasks) support category modification through the `category` parameter 2. **Category Must Exist**: The specified `category` must already be configured in the DocFlow workspace, otherwise an error will be returned 3. **Category Name Matching**: Category names must exactly match the configuration (case-sensitive) 4. **Chinese Category Handling**: If using Chinese category names, ensure the request body uses UTF-8 encoding 5. **Reprocessing After Modification**: After modifying the file category, the system will reprocess the data according to the new category # Specify Classification Upload Source: https://docs-docflow.textin.ai/docflow-global/en/04-classify/manual Specify the file category during upload to skip the automatic classification process and proceed directly to extraction. When you already know the document category, you can specify the file category through the `category` parameter during file upload, so DocFlow will skip the automatic classification process and go directly to the extraction stage. The specified `category` must be a file category that has been configured in the DocFlow workspace, otherwise processing will fail. Manual classification can save processing time and is particularly suitable for batch processing scenarios with the same type of documents. ## Use Cases 1. **Batch processing of same type documents**: Such as batch processing invoices, contracts, etc. 2. **Known document types**: Document category is determined before uploading files 3. **Improve processing efficiency**: Skip classification step and go directly to extraction stage ## Specify Category During Upload Add the `category` parameter to the file upload interface to achieve manual classification: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/invoice.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&category=invoice" ``` ```python Python expandable icon=python lines theme={null} import requests import os from requests_toolbelt.multipart.encoder import MultipartEncoder ti_app_id = "" ti_secret_code = "" workspace_id = "" filepath = "/path/to/invoice.pdf" category = "invoice" # Specify file category host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" payload = MultipartEncoder(fields={ "file": (os.path.basename(filepath), open(filepath, "rb"), mime_type) }) resp = requests.post( url=f"{host}{url}", params={ "workspace_id": workspace_id, "category": category }, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) ``` ## Specify Category for Batch Upload For batch upload, you can specify the same category for all files: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/invoice1.pdf" \ -F "file=@/path/to/invoice2.pdf" \ -F "file=@/path/to/invoice3.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&category=invoice&batch_number=INV-2024-001" ``` ```python Python expandable icon=python lines theme={null} import requests import os from requests_toolbelt.multipart.encoder import MultipartEncoder ti_app_id = "" ti_secret_code = "" workspace_id = "" category = "invoice" batch_number = "INV-2024-001" # Prepare multiple files files = [ "/path/to/invoice1.pdf", "/path/to/invoice2.pdf", "/path/to/invoice3.pdf" ] # Build multipart data fields = {} for i, filepath in enumerate(files): mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" fields[f"file"] = (os.path.basename(filepath), open(filepath, "rb"), mime_type) payload = MultipartEncoder(fields=fields) resp = requests.post( url="https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload", params={ "workspace_id": workspace_id, "category": category, "batch_number": batch_number }, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) ``` ## Processing Workflow Comparison ### Automatic Classification Workflow ``` Upload → Parse → Automatic Classification → Extract → Complete ``` ### Manual Classification Workflow ``` Upload (specify category) → Parse → Extract → Complete ``` ## Notes 1. **Category must be configured**: The specified `category` must have been configured in the DocFlow workspace, otherwise an error will be returned 2. **Category name matching**: Category name must exactly match what was configured (case-sensitive) 3. **Processing status**: Files with manual classification will skip classification status directly in query results 4. **Error handling**: If the specified category does not exist, file processing will fail. It is recommended to first ensure the category is correctly configured through [Configure File Categories](../100-faq/setup_category) ## Query Processing Results After files with manual classification are processed, you can query results through the `file/fetch` interface: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python expandable icon=python lines theme={null} import requests resp = requests.get( "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch", params={ "workspace_id": "", "file_id": "", }, headers={"x-ti-app-id": "", "x-ti-secret-code": ""}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}") print(f"File name: {f.get('name')}") print(f"Specified category: {f.get('category')}") print(f"Processing status: {f.get('recognition_status')}") ``` ## Return Result Example ```json expandable theme={null} { "code": 200, "result": { "files": [ { "id": "202412190001", "name": "invoice_sample.pdf", "category": "invoice", "recognition_status": 1, "extract_result": { // Extraction result fields } } ] } } ``` ## Chinese File Category Parameter Passing When you need to specify Chinese or other non-English file categories, you need to perform UTF-8 URL encoding on the `category` parameter. ### Encoding Example Use the `urllib.parse.quote()` function to URL encode Chinese category names. ```bash curl icon=terminal wrap theme={null} # Using encoded Chinese category curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/invoice.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&category=%E5%8F%91%E7%A5%A8" ``` ```python Python expandable icon=python lines theme={null} import urllib.parse # Chinese category name chinese_category = "发票" encoded_category = urllib.parse.quote(chinese_category) print(f"Original category: {chinese_category}") print(f"After encoding: {encoded_category}") # Output: Original category: 发票 # Output: After encoding: %E5%8F%91%E7%A5%A8 ``` # Quick Start Source: https://docs-docflow.textin.ai/docflow-global/en/04-classify/quickstart Reference examples to quickly integrate document classification functionality with APIs After [configuring file classification templates](../100-faq/setup_category) in the DocFlow workspace settings page, when files are uploaded subsequently without specifying the file type, Docflow will automatically classify the files for subsequent extraction or review use. File classification use cases: 1. Reimbursement scenarios have different types of documents such as restaurant invoices, taxi invoices, flight itineraries that need classification 2. Logistics import/export scenarios have materials such as import customs declarations, export customs declarations, freight insurance policies, certificates of origin that need classification Classification templates must be configured in the Docflow workspace to use the classification function. Docflow performs the complete parsing->classification->extraction workflow by default.\ If you only want classification results, please refer to the [Classification Only](./target_process) documentation. ## Classification Principle After configuring sample files for classification in Docflow, the files are first parsed. The title, file type, field configuration, classification prompts, and other attributes of the sample files are then vectorized and analyzed. Once new files are uploaded and their parsing is completed, algorithms compare them with the configured classification samples to determine the best-matching classification result. ## Get Classification Results You can query through the result retrieval interface `file/fetch`.\ The interface returns a JSON structure, with file classification information in the `result.files[].category` field. ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python expandable icon=python lines theme={null} import requests resp = requests.get( "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch", params={ "workspace_id": "", "file_id": "", }, headers={"x-ti-app-id": "", "x-ti-secret-code": ""}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f["id"], f.get("name"), " Category:", f.get("category")) ``` ## Classification Result Structure and Status In the return from `file/fetch`, key fields for each file include: * `id`: File ID * `name`: File name * `category`: Classification result (e.g., `invoice`) * `recognition_status`: Recognition status Common statuses (see OpenAPI `RecognitionStatus` for complete values): * `0` Pending recognition * `1` Recognition successful (when complete workflow ends) * `2` Recognition failed * `3` Classifying * `10` Classification complete (only appears as final state when uploading with `target_process=classify`) ### Return Example (Excerpt) ```json expandable theme={null} { "code": 200, "result": { "files": [ { "id": "202412190001", "name": "sample.pdf", "category": "invoice", "recognition_status": 1 } ] } } ``` # Classification Only Source: https://docs-docflow.textin.ai/docflow-global/en/04-classify/target_process Docflow performs the complete parsing->classification->extraction workflow by default.\ If business requirements only need classification results, you can add the `target_process=classify` parameter to the upload interface, and the workflow will terminate after completing classification, skipping the extraction process. ## Upload Files for Classification Only ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/your/file.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&target_process=classify" ``` ```python Python expandable icon=python lines theme={null} import requests from requests_toolbelt.multipart.encoder import MultipartEncoder import os ti_app_id = "" ti_secret_code = "" workspace_id = "" filepath = "/path/to/your/file.pdf" host = "https://docflow.textin.ai" url = "/api/app-api/sip/platform/v2/file/upload" mime_type = "application/pdf" if filepath.lower().endswith((".jpg", ".jpeg", ".png")): mime_type = "image/jpeg" payload = MultipartEncoder(fields={ "file": (os.path.basename(filepath), open(filepath, "rb"), mime_type) }) resp = requests.post( url=f"{host}{url}", params={ "workspace_id": workspace_id, "target_process": "classify" }, data=payload.to_string(), headers={ "Content-Type": payload.content_type, "x-ti-app-id": ti_app_id, "x-ti-secret-code": ti_secret_code, }, timeout=60, ) print(resp.status_code, resp.text) ``` ## Query Classification Results Use the `file/fetch` interface to query classification results: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python expandable icon=python lines theme={null} import requests resp = requests.get( "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch", params={ "workspace_id": "", "file_id": "", }, headers={"x-ti-app-id": "", "x-ti-secret-code": ""}, timeout=60, ) data = resp.json() for f in data.get("result", {}).get("files", []): print(f"File ID: {f['id']}") print(f"File name: {f.get('name')}") print(f"Classification result: {f.get('category')}") print(f"Recognition status: {f.get('recognition_status')}") ``` ## Recognition\_status Status Description for Classification Only When using `target_process=classify` for classification only, the `recognition_status` field will have the following status changes: ### Status Value Description * `0` - Pending recognition: File just uploaded, waiting for processing * `3` - Classifying: Classification processing in progress * `10` - Classification complete: **Final state for classification-only workflow**, indicating classification is complete and extraction will not be performed * `2` - Classification failed: Error occurred during classification process ### Difference from Complete Workflow **Complete workflow (default)** status changes: * `0` → `3` → `4` → `1` (Pending recognition → Classifying → Extracting → Recognition successful) **Classification-only workflow** status changes: * `0` → `3` → `10` (Pending recognition → Classifying → Classification complete) ### Return Example ```json expandable theme={null} { "code": 200, "result": { "files": [ { "id": "202412190001", "name": "invoice.pdf", "category": "invoice", "recognition_status": 10, "data": null } ] } } ``` # Amend File Category (Multi-Image Crop) Source: https://docs-docflow.textin.ai/docflow-global/en/05-split/amend_category_crop For multi-image crop tasks, use the amend category API to modify the category of cropped files ## Overview For completed multi-image crop tasks, if the category of cropped child files is incorrect, you can use the **amend category** API to modify the category of cropped files. This API is used to modify the category of child files generated by multi-image crop tasks (`task_type = 2`, parent task). You need to first obtain the parent task's `task_id` and child task's `crop_child_task_id`. ## Use Cases 1. **Crop Category Correction**: After automatic cropping, some child files have incorrect category recognition and need manual correction 2. **Category Adjustment**: Business requirements change and cropped files need to be reclassified ## API Endpoint **Endpoint**: `POST /api/app-api/sip/platform/v2/file/amend_category` ## Request Parameters | Parameter | Type | Required | Description | | -------------- | ------ | -------- | ------------------------------------------------------------------------------------- | | `workspace_id` | string | Yes | Workspace ID | | `task_id` | string | Yes | Parent task ID (multi-image crop task ID) | | `crop_tasks` | array | Yes | Multi-image crop task list, each element contains `crop_child_task_id` and `category` | ### crop\_tasks Parameter Description | Parameter | Type | Required | Description | | -------------------- | ------ | -------- | ------------------------------ | | `crop_child_task_id` | string | Yes | Multi-image crop child task ID | | `category` | string | Yes | Child task file category | ### Parameter Description * `task_id`: Parent task ID (`task_type = 2`), can be obtained through the `file/fetch` API * `crop_child_task_id`: Child task ID (`task_type = 3`), can be obtained from `child_files` * `category`: New file category name, must be a file category already configured in the DocFlow workspace ## Example Code ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "workspace_id": "1234567890", "task_id": "1234567890", "crop_tasks": [ { "crop_child_task_id": "1981692246135111680", "category": "Electronic Invoice (Regular)" }, { "crop_child_task_id": "1981692246135111681", "category": "Train Ticket" } ] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" ``` ```python Python icon=python expandable theme={null} import requests import json def amend_crop_category(workspace_id, task_id, crop_tasks, app_id, secret_code): """ Amend category for multi-image crop tasks Args: workspace_id: Workspace ID task_id: Parent task ID (multi-image crop task ID) crop_tasks: Crop task list, format: [ { "crop_child_task_id": "Child task ID", "category": "Category name" }, ... ] app_id: Application ID secret_code: Secret code """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "crop_tasks": crop_tasks } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example if __name__ == "__main__": WORKSPACE_ID = "1234567890" PARENT_TASK_ID = "1234567890" # Parent task ID (task_type = 2) APP_ID = "" SECRET_CODE = "" # Define crop tasks: modify category for different child files crop_tasks = [ { "crop_child_task_id": "1981692246135111680", # Child task ID "category": "Electronic Invoice (Regular)" }, { "crop_child_task_id": "1981692246135111681", "category": "Train Ticket" } ] result = amend_crop_category(WORKSPACE_ID, PARENT_TASK_ID, crop_tasks, APP_ID, SECRET_CODE) print(json.dumps(result, indent=2, ensure_ascii=False)) ``` ## Get Parent Task ID and Child File Information Before modifying the file category, you need to obtain the parent task's `task_id` and child file's `crop_child_task_id`. You can query it through the `file/fetch` API: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python icon=python expandable theme={null} import requests import json def get_crop_task_info(workspace_id, file_id, app_id, secret_code): """ Get multi-image crop task information, including parent task ID and child file information """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = { "workspace_id": workspace_id, "file_id": file_id } response = requests.get(url, headers=headers, params=params) data = response.json() files = data.get("result", {}).get("files", []) if files: file_data = files[0] task_id = file_data.get("task_id") task_type = file_data.get("task_type") child_files = file_data.get("child_files", []) # Extract child file information crop_children = [] for child in child_files: if child.get("task_type") == 3: # Child files generated by multi-image crop crop_children.append({ "crop_child_task_id": child.get("task_id"), "category": child.get("category"), "name": child.get("name"), "from_parent_position_list": child.get("from_parent_position_list", []), "crop_info": child.get("crop_info", {}) }) return { "parent_task_id": task_id, "parent_task_type": task_type, "crop_children": crop_children } return None # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" APP_ID = "" SECRET_CODE = "" task_info = get_crop_task_info(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) if task_info: print("Parent task ID:", task_info["parent_task_id"]) print("Parent task type:", task_info["parent_task_type"]) print("Child file information:") for child in task_info["crop_children"]: print(json.dumps(child, indent=2, ensure_ascii=False)) ``` ## Response After successfully modifying the file category, the API returns a success response: ```json expandable theme={null} { "code": 200, "msg": "success" } ``` ## Complete Example The following is a complete example showing how to query multi-image crop task information and then modify child file categories: ```python Python icon=python expandable theme={null} import requests import json def get_crop_task_info(workspace_id, file_id, app_id, secret_code): """Get multi-image crop task information""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = {"workspace_id": workspace_id, "file_id": file_id} response = requests.get(url, headers=headers, params=params) return response.json() def amend_crop_category(workspace_id, task_id, crop_tasks, app_id, secret_code): """Amend category for multi-image crop tasks""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "crop_tasks": crop_tasks } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" APP_ID = "" SECRET_CODE = "" # 1. Get multi-image crop task information file_info = get_crop_task_info(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) files = file_info.get("result", {}).get("files", []) if files: file_data = files[0] parent_task_id = file_data.get("task_id") task_type = file_data.get("task_type") child_files = file_data.get("child_files", []) # Confirm it's a multi-image crop parent task (task_type = 2) if task_type == 2: print(f"Parent task ID: {parent_task_id}") print("Current child file information:") # Build crop_tasks parameter crop_tasks = [] for child in child_files: if child.get("task_type") == 3: # Child files generated by multi-image crop crop_child_task_id = child.get("task_id") current_category = child.get("category") child_name = child.get("name") print(f" - Child task ID: {crop_child_task_id}") print(f" File name: {child_name}") print(f" Current category: {current_category}") # Example: Modify category for all child files # You can modify this based on actual requirements, such as judging by file name or other conditions crop_tasks.append({ "crop_child_task_id": crop_child_task_id, "category": "Electronic Invoice (Regular)" # New category, can be modified based on actual requirements }) # 2. Amend file category if crop_tasks: result = amend_crop_category(WORKSPACE_ID, parent_task_id, crop_tasks, APP_ID, SECRET_CODE) print(f"Amendment result: {json.dumps(result, indent=2, ensure_ascii=False)}") else: print(f"This task is not a multi-image crop parent task (task_type={task_type})") ``` ## Child Task ID Notes * `crop_child_task_id` is the child task's `task_id`, which can be obtained from the `child_files` returned by the `file/fetch` API * Each child file generated by multi-image crop has a unique `task_id` * Child files have `task_type` of `3`, indicating they are generated by multi-image crop ## Notes 1. **Task Type Restriction**: Only multi-image crop parent tasks (`task_type = 2`) support using the `crop_tasks` parameter 2. **Category Must Exist**: The specified `category` must already be configured in the DocFlow workspace, otherwise an error will be returned 3. **Category Name Matching**: Category names must exactly match the configuration (case-sensitive) 4. **Child Task ID Must Be Valid**: Ensure `crop_child_task_id` is a valid child task ID 5. **Reprocessing After Modification**: After modifying the file category, the system will reprocess data according to the new category # Amend File Category (File Split) Source: https://docs-docflow.textin.ai/docflow-global/en/05-split/amend_category_split For file split tasks, use the amend category API to modify the category and page numbers of split files ## Overview For completed file split tasks, if the category of split child files is incorrect or you need to adjust the page range of child files, you can use the **amend category** API to modify the category and page numbers of split files. This API is used to modify the category and page numbers of child files generated by file split tasks (`task_type = 2`, parent task). You need to first obtain the parent task's `task_id`. ## Use Cases 1. **Split Category Correction**: After automatic splitting, some child files have incorrect category recognition and need manual correction 2. **Page Range Adjustment**: The page range of split files needs adjustment, such as merging or re-dividing multiple child files ## API Endpoint **Endpoint**: `POST /api/app-api/sip/platform/v2/file/amend_category` ## Request Parameters | Parameter | Type | Required | Description | | -------------- | ------ | -------- | ------------------------------------------------------------------ | | `workspace_id` | string | Yes | Workspace ID | | `task_id` | string | Yes | Parent task ID (file split task ID) | | `split_tasks` | array | Yes | File split task list, each element contains `category` and `pages` | ### split\_tasks Parameter Description | Parameter | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------------------- | | `category` | string | Yes | Child task file category | | `pages` | array | Yes | Child file page number array, starting from 0 | ### Parameter Description * `task_id`: Parent task ID (`task_type = 2`), can be obtained through the `file/fetch` API * `category`: New file category name, must be a file category already configured in the DocFlow workspace. If a child file doesn't need category modification, you can keep the original category unchanged * `pages`: Page number array indicating the original file pages contained in this child file. For example, `[0, 1]` means pages 1 and 2 (starting from 0). If a child file doesn't need page number modification, you can keep the original page numbers unchanged **Important**: The `split_tasks` array must contain **all** split child file information, even if some child files don't need category or page number modifications. If only partial child file information is submitted, the unlisted child files will be deleted or cause processing exceptions. ## Example Code ```bash curl icon=terminal wrap theme={null} # Important: Must include all split child file information # Assuming the original file is split into 3 child files, even if you only need to modify the first child file's category, # you must include information for all 3 child files curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -H "Content-Type: application/json" \ -d '{ "workspace_id": "1234567890", "task_id": "1234567890", "split_tasks": [ { "category": "Electronic Invoice (Regular)", "pages": [0, 1] }, { "category": "Contract", "pages": [2, 3, 4] }, { "category": "Receipt", "pages": [5, 6] } ] }' \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" ``` ```python Python icon=python expandable theme={null} import requests import json def amend_split_category(workspace_id, task_id, split_tasks, app_id, secret_code): """ Amend category and page numbers for file split tasks Args: workspace_id: Workspace ID task_id: Parent task ID (file split task ID) split_tasks: Split task list, format: [ { "category": "Category name", "pages": [0, 1] # Page number array, starting from 0 }, ... ] app_id: Application ID secret_code: Secret code """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "split_tasks": split_tasks } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example if __name__ == "__main__": WORKSPACE_ID = "1234567890" PARENT_TASK_ID = "1234567890" # Parent task ID (task_type = 2) APP_ID = "" SECRET_CODE = "" # Important: Must include all split child file information # Assuming the original file is split into 3 child files: # - Child file 1: Pages 1-2, category "Invoice" # - Child file 2: Pages 3-5, category "Contract" # - Child file 3: Pages 6-7, category "Receipt" # # If you only need to modify child file 1's category, you must also include information for child files 2 and 3 split_tasks = [ { "category": "Electronic Invoice (Regular)", # Modified category "pages": [0, 1] # Keep original page numbers }, { "category": "Contract", # Keep original category "pages": [2, 3, 4] # Keep original page numbers }, { "category": "Receipt", # Keep original category "pages": [5, 6] # Keep original page numbers (Note: original file pages 6-7 correspond to page numbers 5-6) } ] result = amend_split_category(WORKSPACE_ID, PARENT_TASK_ID, split_tasks, APP_ID, SECRET_CODE) print(json.dumps(result, indent=2, ensure_ascii=False)) ``` ## Get Parent Task ID and Child File Information Before modifying the file category, you need to obtain the parent task's `task_id` and child file information. You can query it through the `file/fetch` API: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&file_id=" ``` ```python Python icon=python expandable theme={null} import requests import json def get_split_task_info(workspace_id, file_id, app_id, secret_code): """ Get file split task information, including parent task ID and child file information """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = { "workspace_id": workspace_id, "file_id": file_id } response = requests.get(url, headers=headers, params=params) data = response.json() files = data.get("result", {}).get("files", []) if files: file_data = files[0] task_id = file_data.get("task_id") task_type = file_data.get("task_type") child_files = file_data.get("child_files", []) # Extract child file information split_children = [] for child in child_files: if child.get("task_type") == 0: # Child files generated by file split split_children.append({ "task_id": child.get("task_id"), "category": child.get("category"), "pages": child.get("pages", {}).get("pages", []) if isinstance(child.get("pages"), dict) else child.get("pages", []) }) return { "parent_task_id": task_id, "parent_task_type": task_type, "split_children": split_children } return None # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" APP_ID = "" SECRET_CODE = "" task_info = get_split_task_info(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) if task_info: print("Parent task ID:", task_info["parent_task_id"]) print("Parent task type:", task_info["parent_task_type"]) print("Child file information:") for child in task_info["split_children"]: print(json.dumps(child, indent=2, ensure_ascii=False)) ``` ## Response After successfully modifying the file category, the API returns a success response: ```json expandable theme={null} { "code": 200, "msg": "success" } ``` ## Complete Example The following is a complete example showing how to query file split task information and then modify child file categories and page numbers: ```python Python icon=python expandable theme={null} import requests import json def get_split_task_info(workspace_id, file_id, app_id, secret_code): """Get file split task information""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = {"workspace_id": workspace_id, "file_id": file_id} response = requests.get(url, headers=headers, params=params) return response.json() def amend_split_category(workspace_id, task_id, split_tasks, app_id, secret_code): """Amend category and page numbers for file split tasks""" url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/amend_category" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code, "Content-Type": "application/json" } payload = { "workspace_id": workspace_id, "task_id": task_id, "split_tasks": split_tasks } response = requests.post(url, headers=headers, json=payload) return response.json() # Usage example WORKSPACE_ID = "1234567890" FILE_ID = "202412190001" APP_ID = "" SECRET_CODE = "" # 1. Get file split task information file_info = get_split_task_info(WORKSPACE_ID, FILE_ID, APP_ID, SECRET_CODE) files = file_info.get("result", {}).get("files", []) if files: file_data = files[0] parent_task_id = file_data.get("task_id") task_type = file_data.get("task_type") child_files = file_data.get("child_files", []) # Confirm it's a file split parent task (task_type = 2) if task_type == 2: print(f"Parent task ID: {parent_task_id}") print("Current child file information:") # Build split_tasks parameter # Important: Must include all child file information, even if some don't need modification split_tasks = [] for child in child_files: if child.get("task_type") == 0: # Child files generated by file split # Get current page number information pages_info = child.get("pages", []) if isinstance(pages_info, list) and pages_info: # If pages is an object array, extract page numbers pages = [p.get("page") if isinstance(p, dict) else p for p in pages_info] elif isinstance(pages_info, dict): # If pages is a dictionary, try to extract pages array pages = pages_info.get("pages", []) else: # If pages is a simple array, use directly pages = pages_info if isinstance(pages_info, list) else [] current_category = child.get("category") print(f" - Category: {current_category}, Pages: {pages}") # Example: Only modify the first child file's category, keep others unchanged # Note: Must include all child files, even if they don't need modification if len(split_tasks) == 0: # Modify the first child file's category split_tasks.append({ "category": "Electronic Invoice (Regular)", # New category "pages": pages # Keep original page numbers }) else: # Other child files keep original category and page numbers split_tasks.append({ "category": current_category, # Keep original category "pages": pages # Keep original page numbers }) # 2. Amend file category and page numbers # Ensure all child file information is included if split_tasks: print(f"\nPreparing to submit information for {len(split_tasks)} child files") result = amend_split_category(WORKSPACE_ID, parent_task_id, split_tasks, APP_ID, SECRET_CODE) print(f"Amendment result: {json.dumps(result, indent=2, ensure_ascii=False)}") else: print(f"This task is not a file split parent task (task_type={task_type})") ``` ## Page Number Notes * Page numbers start from **0**, meaning page 1 corresponds to page number `0`, page 2 corresponds to page number `1`, and so on * The `pages` array indicates the original file page numbers contained in this child file ## Notes 1. **Must Include All Child Files**: The `split_tasks` array must contain **all** split child file information, even if some child files don't need category or page number modifications. If only partial child file information is submitted, the unlisted child files will be deleted or cause processing exceptions 2. **Task Type Restriction**: Only file split parent tasks (`task_type = 2`) support using the `split_tasks` parameter 3. **Category Must Exist**: The specified `category` must already be configured in the DocFlow workspace, otherwise an error will be returned 4. **Category Name Matching**: Category names must exactly match the configuration (case-sensitive) 5. **Page Range**: Ensure page numbers in the `pages` array are within valid range (0 to total pages - 1), and page numbers cannot be duplicated 6. **No Duplicate Pages**: Each page number can only appear in one child file, no overlapping allowed 7. **Reprocessing After Modification**: After modifying file categories and page numbers, the system will reprocess data according to the new categories and page ranges # Multi-Image Cropping Source: https://docs-docflow.textin.ai/docflow-global/en/05-split/crop Intelligently recognize and crop documents containing multiple independent images on one page, supporting scenarios like expense receipt pasting ## Feature Overview The multi-image cropping function can automatically recognize multiple independent images or tickets contained in one page of a document and separately crop them into independent sub-documents. This is particularly useful for scenarios such as processing reimbursement attachments or scans containing multiple receipts. ## Use Cases ### 1. Expense Receipt Pasting Scenario An A4 paper with multiple tickets laid flat: * Train tickets * Flight itineraries * Multiple taxi invoices * Restaurant invoices Through the multi-image cropping function, each ticket can be separately recognized and cropped, facilitating subsequent classification and amount extraction. crop example ## API Parameter Configuration ### Enable Multi-Image Cropping Function Set `crop_flag=true` in the upload interface to enable the multi-image cropping function: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/multi-image-document.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&crop_flag=true" ``` ### Parameter Description | Parameter Name | Type | Default Value | Description | | -------------- | ------- | ------------- | ----------------------------------------------- | | `crop_flag` | boolean | false | Whether to enable multi-image cropping function | ## Example Code ```python Python expandable icon=python theme={null} import requests import json def upload_with_crop(file_path, workspace_id, app_id, secret_code): """ Upload file and enable multi-image cropping function """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = { "workspace_id": workspace_id, "crop_flag": "true" # Enable multi-image cropping function } with open(file_path, 'rb') as file: files = {'file': file} response = requests.post(url, headers=headers, params=params, files=files) return response.json() def fetch_crop_results(workspace_id, batch_number, app_id, secret_code): """ Query multi-image cropping results """ url = "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch" headers = { "x-ti-app-id": app_id, "x-ti-secret-code": secret_code } params = { "workspace_id": workspace_id, "batch_number": batch_number } response = requests.get(url, headers=headers, params=params) return response.json() def parse_crop_coordinates(from_parent_position_list): """ Parse cropping coordinate information Coordinate format: [x1, y1, x2, y2, x3, y3, x4, y4] Represents the four vertex coordinates of a rectangle """ if len(from_parent_position_list) != 8: return None coordinates = { "top_left": (from_parent_position_list[0], from_parent_position_list[1]), "top_right": (from_parent_position_list[2], from_parent_position_list[3]), "bottom_right": (from_parent_position_list[4], from_parent_position_list[5]), "bottom_left": (from_parent_position_list[6], from_parent_position_list[7]) } # Calculate bounding box x_coords = [coord[0] for coord in coordinates.values()] y_coords = [coord[1] for coord in coordinates.values()] bbox = { "x_min": min(x_coords), "y_min": min(y_coords), "x_max": max(x_coords), "y_max": max(y_coords), "width": max(x_coords) - min(x_coords), "height": max(y_coords) - min(y_coords) } return {"coordinates": coordinates, "bbox": bbox} # Usage example if __name__ == "__main__": # Configuration information WORKSPACE_ID = "your-workspace-id" APP_ID = "your-app-id" SECRET_CODE = "your-secret-code" FILE_PATH = "/path/to/multi-image-document.pdf" # Upload file and enable multi-image cropping upload_result = upload_with_crop(FILE_PATH, WORKSPACE_ID, APP_ID, SECRET_CODE) print("Upload result:", json.dumps(upload_result, indent=2, ensure_ascii=False)) # Get batch number batch_number = upload_result.get("result", {}).get("batch_number") if batch_number: # Query multi-image cropping results fetch_result = fetch_crop_results(WORKSPACE_ID, batch_number, APP_ID, SECRET_CODE) print("Multi-image cropping result:", json.dumps(fetch_result, indent=2, ensure_ascii=False)) # Parse coordinate information files = fetch_result.get("result", {}).get("files", []) for file in files: child_files = file.get("child_files", []) for child in child_files: if child.get("task_type") == 3: # Sub-file generated by multi-image cropping position_list = child.get("from_parent_position_list") if position_list: coord_info = parse_crop_coordinates(position_list) print(f"Coordinate information for sub-file {child.get('name')}:", coord_info) ``` ## Return Result Description ### Multi-Image Cropping Result Structure After enabling the multi-image cropping function, the result returned by the `file/fetch` interface will include the `child_files` field, which describes the information of sub-documents after cropping: ```json expandable theme={null} { "code": 200, "result": { "files": [ { "id": "parent-file-001", "name": "multi-image-document.pdf", "format": "pdf", "child_files": [ { "id": "child-001", "task_id": "task-001", "task_type": 3, // 3 indicates sub-file generated by multi-image cropping "name": "multi-image-document.pdf#1", "format": "pdf", "category": "invoice", "from_parent_position_list": [12, 30, 420, 30, 420, 320, 12, 320], "crop_info":{"page":0,"imageAngle":"0"} "status": "success" }, { "id": "child-002", "task_id": "task-002", "task_type": 3, "name": "multi-image-document.pdf#2", "format": "pdf", "category": "receipt", "from_parent_position_list": [450, 30, 800, 30, 800, 200, 450, 200], "crop_info":{"page":0,"imageAngle":"0"} "status": "success" } ] } ] } } ``` ### Key Field Description | Field Name | Type | Description | | ----------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------- | | `child_files` | array | List of sub-files after cropping | | `child_files[].id` | string | Unique identifier of sub-file | | `child_files[].task_type` | integer | Task type, 3 indicates generated by multi-image cropping | | `child_files[].category` | string | Document classification result | | `child_files[].from_parent_position_list` | array | Coordinates of cropping area in original image, refer to [Coordinate System Description](../03-parse/coordinate) | | `child_files[].crop_info` | object | Detailed information of multi-image cropping, including page index and angle information | # Quick Start Source: https://docs-docflow.textin.ai/docflow-global/en/05-split/quickstart Reference examples to quickly integrate document splitting functionality with APIs ## Feature Overview Document splitting can handle scenarios where a multi-page file contains multiple different types of documents, or multiple tickets are pasted on one page. Document splitting includes two types of capabilities: **file splitting** (split) and **multi-image cropping** (crop) ### File Splitting Automatically split long documents into single pages or sub-documents. Use cases: 1. Medical insurance claims scenario: a multi-page file with pages 1-2 being insurance policies, pages 3-5 being invoices, and pages 6-10 being hospitalization records. 2. Logistics import/export scenario: page 1 is an export customs declaration, page 2 is an invoice, page 3 is a packing list, and page 4 is a sales contract. > 📖 **Detailed Documentation**: See [File Splitting Feature Detailed Documentation](./split) for more use cases, API parameters, and example code. ### Multi-Image Cropping Used for cropping when one page contains multiple independent tickets. Use cases: 1. Expense reimbursement pasting invoices scenario: an A4 paper with train tickets, flight itineraries, multiple taxi invoices laid flat > 📖 **Detailed Documentation**: See [Multi-Image Cropping Feature Detailed Documentation](./crop) for more use cases, API parameters, and example code. Through file splitting and multi-image cropping, different file categories in files can be split out, which can help subsequent extraction processes more accurately extract information from various types of files. ## Feature Enable Parameters File splitting and multi-image cropping functions are disabled by default.\ In the upload interface, the following two parameters control whether to enable file splitting and cropping functions: * `split_flag` Whether to perform file splitting, default `false` * `crop_flag` Whether to perform multi-image cropping, default `false` File splitting and multi-image cropping functions can be used in combination, for example, only enabling file splitting or only enabling multi-image cropping, or enabling both file splitting and multi-image cropping simultaneously. Request example: ```bash curl icon=terminal wrap theme={null} curl -X POST \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ -F "file=@/path/to/long.pdf" \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/upload?workspace_id=&split_flag=true" ``` ## Query Splitting Results Use `file/fetch` to query. The `child_files` field in the response describes sub-task information: ```bash curl icon=terminal wrap theme={null} curl \ -H "x-ti-app-id: " \ -H "x-ti-secret-code: " \ "https://docflow.textin.ai/api/app-api/sip/platform/v2/file/fetch?workspace_id=&batch_number=" ``` Key fields in the return structure include: * `files[].child_files[]`: Sub-task list (exists when splitting or cropping) Where `files[].child_files[].task_type` indicates the splitting task type: * `task_type=0`, indicates the sub-file was generated by file splitting * `task_type=3`, indicates the sub-file was generated by multi-image cropping When files are generated by multi-image cropping, the field `child_files[].from_parent_position_list` represents the coordinates of the cropping result in the original image. The coordinate representation can refer to the [Coordinate System Description](../03-parse/coordinate). ### Return Example (Excerpt) ```json expandable theme={null} { "code": 200, "result": { "files": [ { "id": "parent-001", "name": "multi-photo.pdf", "child_files": [ { "id": "child-001", "task_id": "t-1", "task_type": 0, "name": "multi-photo.pdf#1", "format": "pdf", "category": "invoice", "from_parent_position_list": [12, 30, 420, 30, 420, 320, 12, 320] } ], } ] } } ``` # File Splitting Source: https://docs-docflow.textin.ai/docflow-global/en/05-split/split ## Feature Overview For complex documents containing multiple files of multiple categories, the file splitting function supports intelligent recognition of document content to achieve automatic splitting and classification of documents. ## Use Cases ### 1. Medical Insurance Claims Scenario A multi-page file contains: * Pages 1-2: Insurance policy information * Pages 3-5: Medical invoices * Pages 6-10: Hospitalization records Through the file splitting function, these three different types of documents can be split separately, facilitating subsequent classification and extraction processing. ### 2. Logistics Import/Export Scenario One file contains: * Page 1: Export customs declaration * Page 2: Commercial invoice * Page 3: Packing List * Page 4: Sales contract