Swirls

SWIRLS_

  • How it works
  • Pricing

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6

56 matches

OverviewDeliver client operations10Win and grow accounts8Resolve customer issues6Create and distribute content9Run people and operations5Review money and agreements3Monitor systems and data9Compose dependable work6
← Finance & LegalFormView on GitHub

Invoice Processor

Extracts line items and totals from invoices, flags anomalies, and stores results.

aiswitch

Source

/**
 * Processes invoice documents. Extracts line items and totals,
 * flags anomalies, and stores results.
 */

webhook invoice_received {
  label: "Invoice Received"
  schema: @json {
    {
      "type": "object",
      "required": ["vendor", "invoice_text", "amount"],
      "properties": {
        "vendor": { "type": "string" },
        "invoice_text": { "type": "string" },
        "amount": { "type": "number" },
        "due_date": { "type": "string" }
      }
    }
  }
}

workflow process_invoice {
  label: "Process Invoice"

  root {
    type: code
    label: "Extract invoice"
    code: @ts { return context.nodes.root.input }
    outputSchema: @json {
      {
        "type": "object",
        "properties": {
          "vendor": { "type": "string" },
          "invoice_text": { "type": "string" },
          "amount": { "type": "number" },
          "due_date": { "type": "string" }
        }
      }
    }
  }

  node extract_details {
    type: ai
    label: "Extract line items"
    kind: object
    model: "google/gemini-2.5-flash"
    prompt: @ts {
      return "Extract structured line items from this invoice.\n\nVendor: " + context.nodes.root.output.vendor + "\nTotal: $" + context.nodes.root.output.amount + "\n\n" + context.nodes.root.output.invoice_text
    }
    schema: @json {
      {
        "type": "object",
        "required": ["line_items", "total_matches"],
        "properties": {
          "line_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "description": { "type": "string" },
                "quantity": { "type": "number" },
                "unit_price": { "type": "number" },
                "total": { "type": "number" }
              }
            }
          },
          "total_matches": { "type": "boolean" },
          "discrepancy_note": { "type": "string" }
        }
      }
    }
  }

  node check_anomaly {
    type: switch
    label: "Check for anomalies"
    cases: ["ok", "flagged"]
    router: @ts {
      if (context.nodes.extract_details.output.total_matches) return "ok"
      return "flagged"
    }
  }

  node approve {
    type: code
    label: "Auto-approve"
    code: @ts {
      return {
        status: "approved",
        vendor: context.nodes.root.output.vendor,
        amount: context.nodes.root.output.amount,
        line_items: context.nodes.extract_details.output.line_items.length
      }
    }
  }

  node flag {
    type: code
    label: "Flag for review"
    code: @ts {
      return {
        status: "flagged",
        vendor: context.nodes.root.output.vendor,
        amount: context.nodes.root.output.amount,
        note: context.nodes.extract_details.output.discrepancy_note
      }
    }
  }

  flow {
    root -> extract_details
    extract_details -> check_anomaly
    check_anomaly -["ok"]-> approve
    check_anomaly -["flagged"]-> flag
  }
}

stream invoices {
  label: "Invoices"
  workflow: process_invoice
  version: v1

  versions: {
    v1 {
      schema: @json {
        {
          "type": "object",
          "required": ["status", "vendor", "amount"],
          "properties": {
            "status": { "type": "string" },
            "vendor": { "type": "string" },
            "amount": { "type": "number" },
            "line_items": { "type": "number" },
            "note": { "type": "string" }
          }
        }
      }

      condition: @ts { return true }

      prepare: @ts {
        const approved = context.output.approve
        if (approved) return approved
        return context.output.flag
      }
    }
  }
}

trigger on_invoice {
  webhook:invoice_received -> process_invoice
  enabled: true
}

Flow

Trigger to workflow

invoice_receivedwebhook
process_invoice
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

Workflow nodes

CODE
Code Node
Extract invoice
AI
AI Node
Extract line items
SWITCH
Switch Node
Check for anomalies
CODE
Code Node
Auto-approve
CODE
Code Node
Flag for review
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.