--- title: "Export Evaluator" slug: "export-evaluator" updated: 2025-09-15T09:22:00Z published: 2025-09-15T09:22:00Z canonical: "knowledge-base.rossum.ai/export-evaluator" --- > ## Documentation Index > Fetch the complete documentation index at: https://knowledge-base.rossum.ai/llms.txt > Use this file to discover all available pages before exploring further. # Export Evaluator Export evaluator is a piece of a custom code that evaluates the result of API calls and decides whether the export is successful or it has failed. ## Basic export evaluator The easiest export evaluator simply checks whether the condition is met or not: ```python from rossum_python import RossumPython def rossum_hook_request_handler(payload):    r = RossumPython.from_payload(payload)    if eval(payload.get("settings", {}).get("condition")):        r.show_error("Draft invoice not created.")    return r.hook_response() ``` Settings example: ```json {  "condition": "r.field.api1_status_code != '201'" } ``` Note that this example uses `eval` function to evaluate the condition which is considered dangerous if the input is untrusted. ## Coupa export evaluator Coupa REST API typically returns responses in the following format: ```json {  "errors": {    "request": [      {        "invoice-header": [          "Original Invoice Date can't be blank",          "Original Invoice Number can't be blank"        ],        "invoice-header.invoice_lines": ["Total must be negative, make price/quantity negative"],        "invoice-header.invoice_lines.tax_lines": [          "Tax Rate should be present on invoices in Italy"        ]      }    ]  } } ``` To process such responses, we can use the following evaluator (assuming the API responses and statuses are stored in the appropriate datapoints): ```python import json from rossum_python import RossumPython def rossum_hook_request_handler(payload):    x = RossumPython.from_payload(payload)    handle_api_response(x, x.field.api1_status_code, x.field.api1_response_body, "Coupa draft creation", is_error=True)    handle_api_response(x, x.field.api2_status_code, x.field.api2_response_body, "Coupa image scan", is_error=True)    handle_api_response(x, x.field.api3_status_code, x.field.api3_response_body, "Coupa backlink", is_error=True)    handle_api_response(x, x.field.api4_status_code, x.field.api4_response_body, "Coupa submission", is_error=False)    return x.hook_response() def handle_api_response(x, status_code, response_body, message, is_error):    if int(status_code) < 400:        return    response_body = try_parse_json(response_body)    errors = response_body.get('errors', {}).get('request', [{}])[0] if isinstance(response_body, dict) else None    if errors:        for key, messages in errors.items():            for msg in messages:                display_msg = f"{message} ({key}): {msg.strip()}"                (x.show_error if is_error else x.show_warning)(display_msg)    else:        (x.show_error if is_error else x.show_warning)(f"{message}: unhandled error") def try_parse_json(response_body):    try:        return json.loads(response_body)    except json.JSONDecodeError:        return response_body ``` > [!WARNING] > 💬 YOUR FEEDBACK MATTERS! > > Help us keep this page accurate and useful. Select **Yes** or **No** below, then use the feedback form to propose a correction, ask for clarification, or request a new article.