Skip to content

Expense Approval Workflow

A comprehensive expense approval workflow demonstrating conditional routing, form integration, and automated processing. This real-world example shows how to handle employee expense reimbursements with intelligent routing based on amount and expense type.

This expense approval process handles employee expense reimbursements with automatic routing based on expense amount, type, and business rules.

The expense form captures all necessary information for approval routing and reimbursement processing:

form:
fields:
- name: "expense_type"
type: "select"
label: "Expense Type"
required: true
options:
- value: "travel"
label: "Travel & Transportation"
- value: "meals"
label: "Meals & Entertainment"
- value: "office"
label: "Office Supplies"
- value: "training"
label: "Training & Education"
- value: "other"
label: "Other Business Expense"
- name: "total_amount"
type: "currency"
label: "Total Amount"
required: true
validation:
min: 0.01
max: 10000
- name: "expense_date"
type: "date"
label: "Expense Date"
required: true
- name: "description"
type: "textarea"
label: "Description"
required: true
placeholder: "Provide details about the business purpose"
- name: "receipts"
type: "file_upload"
label: "Receipts"
required: true
accept: ".pdf,.jpg,.png"
multiple: true
- name: "business_purpose"
type: "textarea"
label: "Business Purpose"
required: true
placeholder: "Explain how this expense relates to business activities"
name: "Expense Reimbursement"
description: "Employee expense reimbursement approval workflow"
type: "expense_approval"
workflow:
# Step 1: Manager Approval
manager_approval:
name: "manager_approval"
type: "decision"
description: "Manager Review"
approver: "${requestor.manager}"
# Manager can approve, reject, or request more info
on_approve:
continue_to: "amount_check"
on_request_info:
text: "Request More Information"
continue_to: "info_request"
require_comments: true
on_reject:
notify_requestor: "Expense report denied by manager"
end_workflow: true
# Step 1a: Information Request Handling
info_request:
name: "info_request"
type: "notification"
description: "Additional Information Requested"
recipients:
- email: "${requestor.email}"
notification:
message:
subject: "Additional Information Needed"
body: "Your manager has requested additional information for your expense report"
on_complete:
continue_to: "manager_approval" # Return to manager
# Step 2: Amount-based routing
amount_check:
name: "amount_check"
type: "conditional_split"
description: "Amount-based Routing"
choices:
# High-value expenses need finance approval
- conditions: "total_amount > 500"
continue_to: "finance_approval"
# Travel expenses over $300 need additional documentation
- conditions: "expense_type == 'travel' and total_amount > 300"
continue_to: "travel_documentation_check"
# Small expenses go straight to processing
default:
continue_to: "processing"
# Step 3a: Finance Team Approval (for high-value expenses)
finance_approval:
name: "finance_approval"
type: "decision"
description: "Finance Team Approval"
approver: "finance_team"
on_approve:
continue_to: "processing"
on_request_documentation:
text: "Request Additional Documentation"
continue_to: "documentation_request"
require_comments: true
on_reject:
notify_requestor: "High-value expense denied by finance team"
end_workflow: true
# Step 3b: Travel Documentation Check
travel_documentation_check:
name: "travel_documentation_check"
type: "conditional_split"
description: "Verify Travel Documentation"
choices:
# If travel documentation is complete, proceed
- conditions: "travel_documentation_complete == true"
continue_to: "processing"
# Otherwise request missing documentation
default:
continue_to: "travel_documentation_request"
# Step 4: Documentation Request
documentation_request:
name: "documentation_request"
type: "notification"
description: "Request Additional Documentation"
recipients:
- email: "${requestor.email}"
notification:
message:
subject: "Additional Documentation Required"
body: "Additional documentation required for your expense report"
on_complete:
continue_to: "finance_approval" # Return to finance
travel_documentation_request:
name: "travel_documentation_request"
type: "notification"
description: "Request Travel Documentation"
recipients:
- email: "${requestor.email}"
notification:
message:
subject: "Travel Documentation Needed"
body: "Please provide complete travel documentation (itinerary, boarding passes, etc.)"
on_complete:
continue_to: "travel_documentation_check"
# Step 5: Processing & Reimbursement
processing:
name: "processing"
type: "automatic"
description: "Expense Processing & Reimbursement"
actions:
- update_accounting_system: true
- schedule_reimbursement: true
- update_budget_tracking: true
- send_confirmation_email: true
on_complete:
notify_requestor: "Expense approved and scheduled for reimbursement"
end_workflow: true
# Workflow settings
settings:
timeout:
manager_approval: "72_hours"
finance_approval: "48_hours"
documentation_request: "5_days"
escalation:
- step: "manager_approval"
after_timeout: "notify_department_head"
- step: "finance_approval"
after_timeout: "notify_finance_director"
notifications:
send_reminders: true
reminder_intervals: ["24_hours", "4_hours"]
compliance:
receipt_required: true
policy_check: true
audit_trail: true
  • Amount-based routing: Different paths for high-value vs. standard expenses
  • Type-specific logic: Special handling for travel expenses
  • Documentation requirements: Conditional documentation requests
  • Manager options: Approve, reject, or request more information
  • Finance options: Approve, reject, or request documentation
  • User-friendly button labels: Clear action descriptions
  • Information requests: Workflow returns to previous step after clarification
  • Documentation cycles: Iterative documentation collection
  • System integration: Automatic accounting system updates
  • Payment scheduling: Automated reimbursement processing
  • Notification system: Stakeholder communication
# Context-aware validation rules
- name: "meal_attendees"
type: "text"
label: "Meal Attendees"
required: |
{% if expense_type == 'meals' and total_amount > 50 %}
true
{% else %}
false
{% endif %}
- name: "travel_approval_code"
type: "text"
label: "Travel Approval Code"
required: |
{% if expense_type == 'travel' and total_amount > 1000 %}
true
{% else %}
false
{% endif %}
- name: "expense_items"
type: "line_items"
label: "Expense Details"
required: |
{% if total_amount > 200 %}
true
{% else %}
false
{% endif %}
item_fields:
- name: "item_date"
type: "date"
label: "Date"
required: true
- name: "item_description"
type: "text"
label: "Description"
required: true
- name: "item_amount"
type: "currency"
label: "Amount"
required: true
- name: "item_category"
type: "select"
label: "Category"
options:
- value: "transportation"
label: "Transportation"
- value: "accommodation"
label: "Accommodation"
- value: "meals"
label: "Meals"
- value: "other"
label: "Other"
# Policy compliance checks
policy_validation:
name: "policy_validation"
type: "automatic"
description: "Policy Compliance Check"
validation_rules:
- rule: "meal_limit_check"
condition: "expense_type == 'meals'"
validation: "total_amount <= daily_meal_allowance * days"
error_message: "Meal expenses exceed daily allowance"
- rule: "travel_advance_check"
condition: "expense_type == 'travel'"
validation: "total_amount <= (travel_advance + 500)"
error_message: "Travel expenses exceed advance plus $500"
on_pass:
continue_to: "manager_approval"
on_fail:
notify_requestor: "Expense violates company policy"
continue_to: "policy_exception_request"
# Accounting system integration
accounting_integration:
name: "accounting_integration"
type: "automatic"
description: "Update Financial Systems"
integrations:
- system: "quickbooks"
action: "create_expense_entry"
data:
account: "6400" # Travel & Entertainment
amount: "${total_amount}"
description: "${description}"
date: "${expense_date}"
- system: "payroll"
action: "schedule_reimbursement"
data:
employee_id: "${requestor.employee_id}"
amount: "${total_amount}"
pay_period: "next"
- system: "budget_tracker"
action: "update_department_budget"
data:
department: "${requestor.department}"
category: "${expense_type}"
amount: "${total_amount}"
on_complete:
notify_requestor: "Expense processed and payment scheduled"
end_workflow: true

The expense approval workflow automatically tracks:

  • Approval times by manager and expense type
  • Rejection rates and common rejection reasons
  • Processing times from submission to payment
  • Policy compliance rates and violations
  • Department spending patterns and trends
reporting:
expense_analytics:
metrics:
- average_approval_time
- expense_volume_by_department
- rejection_rate_by_manager
- policy_violation_frequency
dashboards:
- name: "Manager Dashboard"
audience: "managers"
metrics: ["team_expenses", "approval_times"]
- name: "Finance Dashboard"
audience: "finance_team"
metrics: ["expense_trends", "budget_utilization"]
  1. Unit Testing: Test individual workflow steps
  2. Integration Testing: Verify external system connections
  3. User Acceptance Testing: Validate with actual users
  4. Load Testing: Test with expected expense volume
  1. Pilot Program: Start with one department
  2. Training Sessions: Educate users on new process
  3. Gradual Rollout: Expand to additional departments
  4. Monitoring: Track performance and user feedback

Related Workflows: