Selected work

Returns portal

One click processes a return in the ticketing system and the ERP. Handling time fell by 65 % to under five minutes.

WebhookShop, ticketing, mailboxScheduleCron, pg_cronOrchestratorn8n, WindmillQueueJobs table, batchesAgentStructured output, toolsLookupERP, catalogueExtractJSON schemaWriteRecords, emailsLLM gatewayLiteLLM, keys and limitsModelQwen on vLLMMCP serverFastAPI over PocketBaseDatabasePocketBase, Supabase, PostgresHostingDocker, small serversEdgeCloudflareObservabilityRun logs, alerts
The parts of the system this work ran through.

Context

An e-commerce company selling fitness equipment through its own shops and large marketplaces across Europe. Every return touched the ticketing system, the ERP and the warehouse, and each step was done by hand in a different tool.

The job

Decisions

Workflows in Windmill, not in the ERP
The ERP and the ticketing system stay the systems of record. Windmill holds the process, calls both through their APIs and keeps every run visible. A change to the process is a script change, not a vendor ticket.
One return equals one idempotent job
Each click creates a job keyed by the return. A retry after a failed ERP call can never book the same return twice, and support can press the button again without fear.
Humans keep the decision, the system does the typing
Support decides refund or replacement; everything after that decision is automated. That split is why the process got faster without losing control over money.
Status visible to the customer
The customer portal reads the same state the employee portal writes, so “where is my return” tickets stopped being a separate workload.

Outcome

Stack: Windmill, TypeScript, REST APIs of the ERP and the ticketing system, PostgreSQL.