Skip to main content
This document introduces how to get review task results via REST API. Review tasks are executed asynchronously. After creating a task, you need to periodically query the review status until the review is completed, then get detailed review results.
Review tasks are executed asynchronously. After creating a task, you need to query review status and results via the interface. This document introduces how to get review results and use them.

Get Review Task Results

Get detailed results of a review task:
curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-ti-app-id: <your-app-id>" \
  -H "x-ti-secret-code: <your-secret-code>" \
  -d '{
    "workspace_id": "<your-workspace-id>",
    "task_id": "31415926"
  }' \
  "https://docflow.textin.com/api/app-api/sip/platform/v2/review/task/result"
Request Parameters:
  • workspace_id (required): Workspace ID
  • task_id (required): Review task ID
Response Example:
{
  "code": 200,
  "msg": "success",
  "result": {
    "task_id": "31415926",
    "task_name": "Review Task 1",
    "status": 1,
    "rule_repo": {
      "repo_id": "31415926",
      "name": "Review Rule Repository 1"
    },
    "extract_task_ids": ["1234567890", "1234567891"],
    "statistics": {
      "pass_count": 100,
      "failure_count": 10,
      "error_count": 0
    },
    "groups": [
      {
        "group_id": "31415926",
        "group_name": "Review Rule Group 1",
        "review_tasks": [
          {
            "rule_task_id": "31415926",
            "rule_id": "31415926",
            "rule_name": "Review Rule 1",
            "risk_level": 10,
            "prompt": "Review rule prompt",
            "review_result": 1,
            "reasoning": "Review reasoning",
            "anchors": [
              {
                "start_pos": 0,
                "end_pos": 10,
                "text": "Original text",
                "vertices": [0, 0, 100, 0, 100, 100, 0, 100],
                "file_id": "file_id"
              }
            ]
          }
        ]
      }
    ]
  }
}

Response Structure Description

Basic Task Information

  • task_id: Review task ID
  • task_name: Task name
  • status: Task status (see status description below)
  • rule_repo: Rule repository information used
  • extract_task_ids: List of extraction task IDs being reviewed

Task Status (status)

Task status represents the overall execution status of the review task:
  • 0: Pending
  • 1: Approved
  • 2: Review failed
  • 3: Reviewing
  • 4: Rejected
  • 5: Recognizing
  • 6: In Queue
  • 7: Recognition Failed

Statistics

  • pass_count: Number of rules that passed review
  • failure_count: Number of rules that failed review
  • error_count: Number of task execution errors

Rule Group Results (groups)

Review results are organized by rule groups. Each rule group contains review results for multiple rules:
  • group_id: Rule group ID
  • group_name: Rule group name
  • review_tasks: List of rule review results

Rule Review Results (review_tasks)

Each rule’s review result contains:
  • rule_task_id: Review subtask ID
  • rule_id: Review rule ID
  • rule_name: Review rule name
  • risk_level: Risk level (10: high risk, 20: medium risk, 30: low risk)
  • prompt: Review rule prompt
  • review_result: Review result (see review result description below)
  • reasoning: Review reasoning, the review reason given by AI
  • anchors: Position anchor information, used to locate the position of review reasoning in the original text

Review Result (review_result)

Review result represents the review status of a single rule:
  • 0: Pending
  • 1: Approved
  • 2: Review failed
  • 3: Reviewing
  • 4: Rejected
  • 5: Recognizing
  • 6: In Queue
  • 7: Recognition Failed

Position Anchors (anchors)

Position anchor information is used to locate the position of review reasoning in the original text:
  • start_pos: Starting character position in reasoning
  • end_pos: Ending character position in reasoning
  • text: Original text content
  • vertices: Bounding quadrilateral coordinates of original text [x1, y1, x2, y2, x3, y3, x4, y4]
  • file_id: File ID

Poll Review Status

Since review tasks are executed asynchronously, you need to periodically query the review status until the review is completed:
Python
import requests
import time

ti_app_id = "<your-app-id>"
ti_secret_code = "<your-secret-code>"
workspace_id = "<your-workspace-id>"
task_id = "31415926"

host = "https://docflow.textin.com"
url = "/api/app-api/sip/platform/v2/review/task/result"

def poll_review_result(max_wait_time=300, poll_interval=5):
    """Poll review results until review is completed or timeout"""
    start_time = time.time()
    
    while True:
        payload = {
            "workspace_id": workspace_id,
            "task_id": task_id
        }
        
        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=60,
        )
        
        result = resp.json()
        if result.get("code") != 200:
            print(f"Query failed: {result.get('msg')}")
            return None
        
        review_result = result.get("result", {})
        status = review_result.get("status")
        
        # Completed statuses: 1(Approved), 2(Review failed), 7(Recognition Failed)
        if status in [1, 2, 7]:
            print(f"Review completed, status: {status}")
            return review_result
        
        # In-progress statuses: 0(Pending), 3(Reviewing), 4(Rejected), 5(Recognizing), 6(In Queue)
        if status in [0, 3, 4, 5, 6]:
            elapsed = time.time() - start_time
            if elapsed >= max_wait_time:
                print(f"Wait timeout, current status: {status}")
                return review_result
            
            print(f"Review in progress, status: {status}, waiting {poll_interval} seconds before retry...")
            time.sleep(poll_interval)
            continue
        
        # Unknown status
        print(f"Unknown status: {status}")
        return review_result

# Poll review results
review_result = poll_review_result(max_wait_time=300, poll_interval=5)
if review_result:
    print(f"Task Name: {review_result.get('task_name')}")
    print(f"Task Status: {review_result.get('status')}")
    print(f"Statistics: {review_result.get('statistics')}")

Process Review Results

Example of parsing and processing review results:
Python
import requests

def process_review_result(review_result):
    """Process review results"""
    task_name = review_result.get("task_name")
    status = review_result.get("status")
    statistics = review_result.get("statistics", {})
    groups = review_result.get("groups", [])
    
    print(f"Task Name: {task_name}")
    print(f"Task Status: {status}")
    print(f"Pass Count: {statistics.get('pass_count', 0)}")
    print(f"Failure Count: {statistics.get('failure_count', 0)}")
    print(f"Error Count: {statistics.get('error_count', 0)}")
    print()
    
    # Iterate through rule groups
    for group in groups:
        group_name = group.get("group_name")
        review_tasks = group.get("review_tasks", [])
        
        print(f"Rule Group: {group_name}")
        print(f"  Rule Count: {len(review_tasks)}")
        
        # Iterate through rule review results
        for review_task in review_tasks:
            rule_name = review_task.get("rule_name")
            review_result_status = review_task.get("review_result")
            reasoning = review_task.get("reasoning", "")
            risk_level = review_task.get("risk_level")
            
            # Review result status mapping
            result_map = {
                0: "Pending",
                1: "Approved",
                2: "Review failed",
                3: "Reviewing",
                4: "Rejected",
                5: "Recognizing",
                6: "In Queue",
                7: "Recognition Failed"
            }
            
            result_text = result_map.get(review_result_status, "Unknown")
            
            # Risk level mapping
            risk_map = {
                10: "High Risk",
                20: "Medium Risk",
                30: "Low Risk"
            }
            risk_text = risk_map.get(risk_level, "Unknown")
            
            print(f"  Rule: {rule_name}")
            print(f"    Risk Level: {risk_text}")
            print(f"    Review Result: {result_text}")
            print(f"    Review Reasoning: {reasoning}")
            
            # Process position anchors
            anchors = review_task.get("anchors", [])
            if anchors:
                print(f"    Position Anchors: {len(anchors)} locations")
                for i, anchor in enumerate(anchors, 1):
                    text = anchor.get("text", "")
                    vertices = anchor.get("vertices", [])
                    file_id = anchor.get("file_id", "")
                    print(f"      [{i}] File: {file_id}, Text: {text[:50]}..., Coordinates: {vertices}")
            
            print()

# Get review results
ti_app_id = "<your-app-id>"
ti_secret_code = "<your-secret-code>"
workspace_id = "<your-workspace-id>"
task_id = "31415926"

host = "https://docflow.textin.com"
url = "/api/app-api/sip/platform/v2/review/task/result"

payload = {
    "workspace_id": workspace_id,
    "task_id": task_id
}

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=60,
)

result = resp.json()
if result.get("code") == 200:
    review_result = result.get("result", {})
    process_review_result(review_result)
else:
    print(f"Failed to get: {result.get('msg')}")

Visualize Using Position Anchors

Position anchor information can be used to highlight the position of review reasoning in the document:
Python
def visualize_anchors(review_result):
    """Visualize using position anchor information"""
    groups = review_result.get("groups", [])
    
    for group in groups:
        review_tasks = group.get("review_tasks", [])
        
        for review_task in review_tasks:
            rule_name = review_task.get("rule_name")
            review_result_status = review_task.get("review_result")
            anchors = review_task.get("anchors", [])
            
            # Only process rules that did not pass
            if review_result_status == 4:  # Review not passed
                print(f"Rule: {rule_name} - Review Not Passed")
                
                # Group by file
                file_anchors = {}
                for anchor in anchors:
                    file_id = anchor.get("file_id")
                    if file_id not in file_anchors:
                        file_anchors[file_id] = []
                    file_anchors[file_id].append(anchor)
                
                # Draw highlight areas for each file
                for file_id, anchors_list in file_anchors.items():
                    print(f"  File ID: {file_id}")
                    print(f"  Number of areas to highlight: {len(anchors_list)}")
                    
                    for anchor in anchors_list:
                        vertices = anchor.get("vertices", [])
                        text = anchor.get("text", "")
                        
                        # Draw rectangle (assuming using some drawing library)
                        # This is just an example, actual implementation depends on your frontend framework
                        print(f"    Text: {text[:30]}...")
                        print(f"    Coordinates: {vertices}")
                        # In actual applications, you can use these coordinates to draw highlight boxes on document images

Complete Example

Complete flow for getting and using review results:
Python
import requests
import time

ti_app_id = "<your-app-id>"
ti_secret_code = "<your-secret-code>"
workspace_id = "<your-workspace-id>"
task_id = "31415926"

host = "https://docflow.textin.com"
url = "/api/app-api/sip/platform/v2/review/task/result"

def get_review_result():
    """Get review results"""
    payload = {
        "workspace_id": workspace_id,
        "task_id": task_id
    }
    
    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=60,
    )
    
    result = resp.json()
    if result.get("code") == 200:
        return result.get("result")
    else:
        print(f"Failed to get: {result.get('msg')}")
        return None

def wait_for_review_complete(max_wait_time=300, poll_interval=5):
    """Wait for review to complete"""
    start_time = time.time()
    
    while True:
        review_result = get_review_result()
        if not review_result:
            return None
        
        status = review_result.get("status")
        
        # Review completed
        if status in [1, 2, 7]:
            return review_result
        
        # Review in progress
        if status in [0, 3, 4, 5, 6]:
            elapsed = time.time() - start_time
            if elapsed >= max_wait_time:
                print("Wait timeout")
                return review_result
            
            print(f"Review in progress, status: {status}, waiting {poll_interval} seconds...")
            time.sleep(poll_interval)
            continue
        
        return review_result

# Wait for review to complete
review_result = wait_for_review_complete()

if review_result:
    # Process review results
    statistics = review_result.get("statistics", {})
    print(f"Pass Count: {statistics.get('pass_count', 0)}")
    print(f"Failure Count: {statistics.get('failure_count', 0)}")
    
    # Find rules that did not pass
    groups = review_result.get("groups", [])
    for group in groups:
        review_tasks = group.get("review_tasks", [])
        for review_task in review_tasks:
            if review_task.get("review_result") == 4:  # Review not passed
                rule_name = review_task.get("rule_name")
                reasoning = review_task.get("reasoning", "")
                print(f"Rule Not Passed: {rule_name}")
                print(f"Review Reasoning: {reasoning}")

Notes

  1. Asynchronous Execution: Review tasks are executed asynchronously. After creating a task, you need to periodically query the review status
  2. Status Judgment: Use the status field to judge task status. 1 means Approved, 4 means Rejected
  3. Position Anchors: Use anchors information to highlight the position of review reasoning in the document