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

# Big invoices need a human

> Send the invoices over your approval limit down a second branch, and let the rest through untouched

Most invoices should just go through. The ones over your approval limit should not. An [If/Else](/guides/nodes/if-else) node tests a field the [Extract](/guides/nodes/extract) node produced and sends the document down a **True** or a **False** branch, so the expensive work, and the person, only get involved when the number says so.

<div className="af-payoff">
  <div className="af-payoff-pane">
    <div className="af-payoff-cap">
      {'Total 4 594.62, limit 4 000'}
    </div>

    <div className="af-payoff-line">
      <span className="af-cite">
        {'condition true'}
      </span>
    </div>

    <div className="af-payoff-line"><span className="af-payoff-key">invoice\_number</span><b>{'INV-2026-9001'}</b></div>
    <div className="af-payoff-line"><span className="af-payoff-key">total\_amount</span><b>{'4594.62'}</b></div>
    <div className="af-payoff-line"><span className="af-payoff-key">bill\_to\_name</span><b>{'Nguyen, Smith…'}</b></div>
    <div className="af-payoff-line"><span className="af-payoff-key">due\_date</span><b>{'2026-03-22'}</b></div>

    <div className="af-payoff-line">
      <span className="af-cite">
        {'↳ 2 extractions: it took the branch'}
      </span>
    </div>
  </div>

  <div className="af-payoff-arrow">→</div>

  <div className="af-payoff-pane">
    <div className="af-payoff-cap">
      {'Same invoice, limit 10 000'}
    </div>

    <div className="af-payoff-line">
      <span className="af-cite">
        {'condition false'}
      </span>
    </div>

    <div className="af-payoff-line"><span className="af-payoff-key">invoice\_number</span><b>{'INV-2026-9001'}</b></div>
    <div className="af-payoff-line"><span className="af-payoff-key">total\_amount</span><b>{'4594.62'}</b></div>

    <div className="af-payoff-line">
      {' '}
    </div>

    <div className="af-payoff-line">
      {' '}
    </div>

    <div className="af-payoff-line">
      <span className="af-cite">
        {'↳ 1 extraction: the branch never ran'}
      </span>
    </div>
  </div>
</div>

<div className="af-cost">
  <span><b>Nodes</b><strong>{'Parse → Extract → If/Else → Extract'}</strong></span>
  <span><b>Credits</b><strong>60 per page</strong>{', plus 35 only when the branch is taken. If/Else is free.'}</span>
  <span><b>You get</b>{' the cheap path for most documents'}</span>
</div>

## The workflow

The condition names a field from the Extract node above it, an operator, and a value. The edge that leaves the If/Else node carries `"branch": "true"` or `"branch": "false"`.

<CodeGroup>
  ```json API theme={null}
  {
    "name": "Large invoices need a human",
    "description": "Route an invoice over the approval limit to a second look",
    "nodes": [
      { "id": "parse_1", "type": "parse" },
      {
        "id": "extract_1",
        "type": "extract",
        "extraction_schema": {
          "fields": [
            { "name": "invoice_number", "description": "The unique invoice identifier", "data_type": "string" },
            { "name": "vendor_name",    "description": "Name of the company that issued the invoice", "data_type": "string" },
            { "name": "total_amount",   "description": "Final total amount due including tax", "data_type": "float" }
          ]
        }
      },
      {
        "id": "if_else_1",
        "type": "if_else",
        "condition": {
          "type": "comparison",
          "left": "total_amount",
          "op": ">",
          "right": { "source": "literal", "value": 4000 }
        }
      },
      {
        "id": "extract_2",
        "type": "extract",
        "extraction_schema": {
          "fields": [
            { "name": "bill_to_name", "description": "The party the invoice is billed to", "data_type": "string" },
            { "name": "due_date",     "description": "Date by which payment is due", "data_type": "date" }
          ]
        }
      }
    ],
    "edges": [
      { "source": "parse_1",   "target": "extract_1" },
      { "source": "extract_1", "target": "if_else_1" },
      { "source": "if_else_1", "target": "extract_2", "branch": "true" }
    ]
  }
  ```

  ```python Python theme={null}
  import os

  from anyformat.sdk import Client
  from anyformat.workflow import (
      ComparisonCheck, Edge, ExtractNode, ExtractionSchema,
      IfElseNode, ParseNode, Schema, WorkflowDefinition,
  )

  client = Client(api_key=os.environ["ANYFORMAT_API_KEY"])

  workflow = client.create_workflow(WorkflowDefinition(
      name="Large invoices need a human",
      nodes=[
          ParseNode(id="parse_1", type="parse"),
          ExtractNode(id="extract_1", type="extract", extraction_schema=ExtractionSchema(fields=[
              Schema.string("invoice_number", "The unique invoice identifier"),
              Schema.string("vendor_name", "Name of the company that issued the invoice"),
              Schema.float("total_amount", "Final total amount due including tax"),
          ])),
          IfElseNode(id="if_else_1", type="if_else", condition=ComparisonCheck(
              type="comparison", left="total_amount", op=">", right={"source": "literal", "value": 4000},
          )),
          ExtractNode(id="extract_2", type="extract", extraction_schema=ExtractionSchema(fields=[
              Schema.string("bill_to_name", "The party the invoice is billed to"),
              Schema.date("due_date", "Date by which payment is due"),
          ])),
      ],
      edges=[
          Edge(source="parse_1", target="extract_1"),
          Edge(source="extract_1", target="if_else_1"),
          Edge(source="if_else_1", target="extract_2", branch="true"),
      ],
  ))
  ```

  ```typescript TypeScript theme={null}
  // The fluent builder has no ifElse() verb yet. Send the API JSON on this page to
  // POST /v3/workflows/, or pass the same graph to af.updateWorkflow(workflowId, definition).
  ```
</CodeGroup>

The fluent Python builder (`client.workflow(...).parse().extract(...)`) has no `if_else()` verb either. Build a `WorkflowDefinition` from the node classes, as above.

## Response

**A run does not tell you which branch it took.** There is no branch field anywhere in the envelope. You read the outcome from what ran: an invoice over the limit comes back with two entries in `extractions`, one per Extract node; the same invoice under the limit comes back with one, because the node on the True branch never ran.

<CodeGroup>
  ```json Over the limit theme={null}
  {
    "status": "processed",
    "results": {
      "extractions": [
        {
          "split_name": null,
          "partition": null,
          "fields": {
            "invoice_number": { "value": "INV-2026-9001", "confidence": 96.0, "evidence": [{ "text": "Invoice #: INV-2026-9001", "page_number": 1 }] },
            "vendor_name":    { "value": "Wayne Enterprises", "confidence": 97.0, "evidence": [{ "text": "From: Wayne Enterprises", "page_number": 1 }] },
            "total_amount":   { "value": "4594.62", "confidence": 97.0, "evidence": [{ "text": "**TOTAL: $4,594.62**", "page_number": 1 }] }
          }
        },
        {
          "split_name": null,
          "partition": null,
          "fields": {
            "bill_to_name": { "value": "Nguyen, Smith and Hickman", "confidence": 96.0, "evidence": [{ "text": "Bill to: Nguyen, Smith and Hickman", "page_number": 1 }] },
            "due_date":     { "value": "2026-03-22", "confidence": 97.0, "evidence": [{ "text": "Due date: 2026-03-22", "page_number": 1 }] }
          }
        }
      ]
    }
  }
  ```

  ```json Under the limit theme={null}
  {
    "status": "processed",
    "results": {
      "extractions": [
        {
          "split_name": null,
          "partition": null,
          "fields": {
            "invoice_number": { "value": "INV-2026-9001", "confidence": 96.0, "evidence": [{ "text": "Invoice #: INV-2026-9001", "page_number": 1 }] },
            "vendor_name":    { "value": "Wayne Enterprises", "confidence": 97.0, "evidence": [{ "text": "From: Wayne Enterprises", "page_number": 1 }] },
            "total_amount":   { "value": "4594.62", "confidence": 97.0, "evidence": [{ "text": "**TOTAL: $4,594.62**", "page_number": 1 }] }
          }
        }
      ]
    }
  }
  ```
</CodeGroup>

## Tell someone about it

An extra Extract node is a placeholder for whatever the branch should do. The usual end of a True branch is a [Slack alert](/guides/nodes/slack-alert): a message in the channel that owns the decision, with the extracted values in it.

```json theme={null}
{
  "id": "slack_1",
  "type": "slack_alert",
  "channel_id": "C0123ABC",
  "channel_name": "#ap-approvals",
  "message_template": "Invoice over the limit from ${field.vendor_name}: ${field.total_amount}. Due ${field.due_date}.",
  "severity": "warning"
}
```

```json theme={null}
{ "source": "if_else_1", "target": "slack_1", "branch": "true" }
```

The alert needs your Slack workspace [connected to the organization](/integrations/slack) first, by an admin, once. Until that is done the node saves fine and sends nothing. Severity sets the colour of the bar on the Slack card and nothing else: it does not decide whether the alert fires, which is what the If/Else above it is for.

## When it goes wrong

**Every document takes the True branch.** The comparison reads the field as a number only when the field is a number. `total_amount` declared as a `string` compares as text, where `"900"` is greater than `"4000"`. Declare amounts as `float`.

**Nothing takes either branch.** The condition names a field that the Extract node above it does not produce. `left` is the field **name**, spelled exactly as in the schema.

**You cannot tell what happened.** Add the alert, or give the False branch its own node too, so each path leaves a trace. Reading the branch from the count of extractions is fine in a script and painful in an audit.

**You want more than one test.** One If/Else node holds one condition. Chain a second node on the branch of the first for "over the limit **and** from a new supplier".

## Next steps

<CardGroup cols={2}>
  <Card title="If/Else" icon="code-branch" href="/guides/nodes/if-else">
    Every operator, and conditions on a validation result
  </Card>

  <Card title="Slack alert" icon="slack" href="/guides/nodes/slack-alert">
    The message template, its placeholders and the severity
  </Card>
</CardGroup>
