.NET automation hub
10+ systems — POS, marketplaces, banking APIs, Gmail, Slack, Google Sheets — wired into ~25 scheduled jobs. Includes idempotent financial reconciliation and bank sweeps, every transaction audit-logged and reported to Slack.
The problem
A US-based ticket-resale business ran on fragmented systems — SkyBox, Lysted, Ticket Evolution, banking APIs, email and spreadsheets. Operations spent hours every day matching sales to inventory, recording payments, watching balances and reading presale emails: repetitive, error-prone work.
What I built
One .NET console application, dispatched by command-line argument from a scheduler, containing ~25 independent sub-programs. Every job shares the same infrastructure — configuration, Serilog logging, Entity Framework data access and a common data-access layer — so adding a job means writing the job, not another service.
- Google Sheets as the operations UI, so non-technical staff can inspect and correct data where they already work.
- Slack as the notification channel, with Block Kit summaries after each run.
- Multimodal LLM email classification (a fine-tuned GPT-4o-mini, interchangeable with Gemini) — see the email-triage case study.
- Idempotent reconciliation and bank sweeps, every transaction audit-logged.
Decisions that mattered
- No API? Use another channel. Where a vendor had no API, the data came from IMAP, parsed HTML templates (HtmlAgilityPack) or Slack conversation history.
- Explicit human-in-the-loop boundaries. When the data is uncertain the job leaves the field blank for a person, instead of guessing.
- Defensive parsing of LLM output with balanced-brace extraction and custom
JsonConverters.
Outcome
Settlement reconciliation, cash sweeps and email triage run on schedule with a full audit trail across systems.
Lessons
A console app plus a scheduler beats microservices for internal automation. Google Sheets is the cheapest operations interface there is. Clear lines between what the machine decides and what a person decides prevent most downstream errors.