> ## 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.

# If/Else

> Tests a condition on the extracted data and sends the document down a True or a False branch. Free.

**If/Else** evaluates one condition against the fields an [Extract](/guides/nodes/extract) node produced, and routes the document to one of two branches: **True** when the condition holds, **False** when it does not. It transforms nothing. It lives in the **Logic** section of the Studio palette and is in **Beta**.

Use it to handle matching and non-matching documents differently: send only invoices over a threshold to a [Slack alert](/guides/nodes/slack-alert), or only documents that failed a [Validate](/guides/nodes/validate) rule.

## The node

<CodeGroup>
  ```json API theme={null}
  {
    "id": "if_else_1",
    "type": "if_else",
    "condition": { "type": "comparison", "left": "total", "op": ">", "right": { "source": "literal", "value": 10000 } }
  }
  ```

  ```python Python theme={null}
  import os
  from anyformat.sdk import Client
  from anyformat.workflow import (
      WorkflowDefinition, Edge,
      ParseNode, ExtractNode, ExtractionSchema, Schema,
      IfElseNode, ComparisonCheck,
  )
  from anyformat.workflow.nodes import SlackAlertNode

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

  workflow = client.create_workflow(WorkflowDefinition(
      name="Large invoices",
      nodes=[
          ParseNode(id="parse_1", type="parse"),
          ExtractNode(id="extract_1", type="extract", extraction_schema=ExtractionSchema(fields=[
              Schema.string("vendor_name", "Vendor name."),
              Schema.float("total", "Grand total."),
          ])),
          IfElseNode(id="if_else_1", type="if_else", condition=ComparisonCheck(
              type="comparison", left="total", op=">", right={"source": "literal", "value": 10000},
          )),
          SlackAlertNode(id="slack_1", type="slack_alert", channel_id="C0123ABC", channel_name="#finance",
              message_template="Large invoice from ${field.vendor_name}: ${field.total}", severity="warning"),
      ],
      edges=[
          Edge(source="parse_1", target="extract_1"),
          Edge(source="extract_1", target="if_else_1"),
          Edge(source="if_else_1", target="slack_1", branch="true"),
      ],
  ))
  ```

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

The Python builder (`client.workflow(...).parse().extract(...)`) has no `if_else()` verb. Build a `WorkflowDefinition` from the node classes instead, as above, and pass it to `create_workflow`. The TypeScript builder has no method either; send the JSON.

The edge that leaves If/Else names its branch: `"branch": "true"` or `"branch": "false"`.

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

A condition names a field by the **name** you gave it on the Extract node. Studio names fields by their persistent id; both forms resolve at run time.

## In Studio

Click the If/Else node on the canvas to open its panel. The **Conditions** list holds one card per condition; with two or more, the **And** / **Or** toggle at the top decides how they combine. Each card has a subject (a field value, field math, a validation outcome, or an expression) and the assertion that completes "Check that the field…"; click **Save condition** when done. The node has two output handles on the canvas, **true** and **false**.

<img src="https://mintcdn.com/anyformat/G2lOO-2_Ah2kKl9r/images/studio-if-else-config.webp?fit=max&auto=format&n=G2lOO-2_Ah2kKl9r&q=85&s=694f502f1a38acc9522f20e1168e0c5f" alt="The If/Else node panel in Studio" width="512" height="271" data-path="images/studio-if-else-config.webp" />

## Options

| Field | Type | Default | What it does |
| - | - | - | - |
| `condition` | check object | required | The condition to evaluate. One check, or an `all_of` / `any_of` combinator of several. |

The schema the API accepts is generated from the same source: [If/Else node schema](/api-reference-v3/node-schemas#if_else).

### Conditions

A condition is a **check**: the same closed set the [Validate](/guides/nodes/validate#checks) node uses, plus one kind that only exists here.

| Check | `type` | What it tests |
| - | - | - |
| **Required** | `required` | The field is present and not empty. |
| **Number in range** | `range` | A numeric field is within `min` and `max`. |
| **Date in range** | `date` | A date field is within `earliest` and `latest`. |
| **Arithmetic** | `arithmetic` | A sum, difference, or product of fields equals another field. |
| **Comparison** | `comparison` | A field compares to a fixed value or another field. |
| **One of** | `one_of` | The field's value is in an allowed set. |
| **Pattern** | `regex` | The field matches a regular expression. |
| **Confidence** | `confidence` | The field's extraction confidence compares to a threshold. |
| **Expression** | `expression` | A CEL expression over the whole extraction. |
| **Validation outcome** | `validation` | An upstream Validate rule ended with `status` (`fail` by default). |
| **All of** / **Any of** | `all_of` / `any_of` | Every / at least one nested check holds. This is what the **And** / **Or** toggle writes. |

The wire shape of each check is on the [Validate](/guides/nodes/validate#check-payloads) page. The `validation` check has its own:

```jsonc theme={null}
// Route on the outcome of the upstream rule "totals-add-up". status: "fail" | "pass" | "inconclusive"
{ "type": "validation", "rule_id": "totals-add-up", "status": "fail" }

// Two conditions combined with And
{ "type": "all_of", "checks": [
  { "type": "validation", "rule_id": "totals-add-up", "status": "fail" },
  { "type": "range", "field": "total", "min": 1000, "max": null }
] }
```

A `validation` condition needs a [Validate](/guides/nodes/validate) node upstream that carries a rule with that `rule_id`. A rule id with no verdict for the document evaluates to inconclusive.

<Note>
  **When a condition can't be evaluated, the document takes the False branch.** If a field the condition refers to is missing, or a confidence check has no confidence score, the condition counts as *not met*, so the document goes down **False**, never **True**. This keeps a True-only branch (like an alert) from firing on data anyformat couldn't actually check. To handle those documents on their own path instead, use a separate, preliminary If/Else node that checks whether the field is **required**, and place the value condition on its True branch.
</Note>

## Connects to

<div className="af-flow" role="img" aria-label="Extract feeds If/Else, whose true and false branches each end in a Slack alert">
  <div className="af-flow-fork">
    <div className="af-fork-in">
      <a className="af-node" href="/guides/nodes/extract">Extract</a>

      <span className="af-link" />

      <a className="af-node af-node-on" href="/guides/nodes/if-else">If/Else</a>
    </div>

    <div className="af-fork-elbow" />

    <div className="af-fork-out">
      <a className="af-node" href="/guides/nodes/slack-alert">Slack alert <span>true</span></a>
      <a className="af-node af-node-opt" href="/guides/nodes/slack-alert">Slack alert <span>false</span></a>
    </div>
  </div>

  <div className="af-flow-note">A <a href="/guides/nodes/validate">Validate</a> node can feed If/Else in place of Extract. The false branch is optional. <a href="/guides/nodes/email-alert">Email alert</a> joins the targets once it ships.</div>
</div>

An [Extract](/guides/nodes/extract) cannot sit after an If/Else today. The API rejects the edge (`an extract node cannot sit downstream of an if_else`) and Studio does not offer it. A second extraction pass on a branch is planned, not available.

## What it returns

Nothing in the run results. If/Else adds no section and changes no field. It decides which downstream nodes run for the document:

* The condition holds: the nodes on the **true** branch run.
* The condition fails, or cannot be evaluated: the nodes on the **false** branch run.

The **true** branch must have at least one node; the API rejects an If/Else with no `"branch": "true"` edge. The **false** branch may be left empty, and the document then stops there. On a workflow with a Split node, the condition is evaluated once per sub-document.

## Billing

Free. If/Else runs no model and bills no credits. Full price list: [How credits work](/concepts/how-credits-work).

## Examples

* [Invoice processing](/examples/invoice-processing): add the If/Else on this page after the Extract to flag invoices over 10,000.
* [Contract analysis](/examples/contract-analysis): route contracts whose expiry date is on or before today to an alert with a `date` condition (`"latest": "today"`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.