Wolt Drive. Built Right.
A delivery API by itself does not prevent wrong-door drop-offs, missed orders, or rejected items that were already out of stock. We built the layer on top that actually does.
The Problems You Only Find
Once You Go Live
The client was rolling out Wolt Drive deliveries from their shop and ran into the kind of issues you only spot once you start using a delivery API in anger. Plugging in the API was the easy part. The problems were all around it.
Wrong Door Deliveries
Customers typed fuzzy addresses and couriers turned up at the wrong place. The API accepted whatever was entered.
No Live Order View
Shop staff had no visibility of incoming orders. They found out about them when something had already gone wrong.
Out-of-Stock Accepts
Orders for out-of-stock items were accepted and only discovered after the courier had already collected the parcel.
No Failure Visibility
Management had no idea where deliveries were failing, what was being rejected, or when the busy hours were.
Four Systems Working Together
The module wraps the Wolt Drive API with validation, real-time alerting, full webhook handling, and analytics. Each part is designed to prevent a specific category of mistake.
A Guided Address Flow That Does Not Trust the Customer
Customers pick a locality from a searchable dropdown, then a street autocomplete filtered to that area. A map appears with a draggable pin and they confirm the position before proceeding. A radius check quietly rejects anything outside the delivery zone. Two map providers are supported: Google Maps for the polished version, OpenStreetMap with Leaflet for the version with no API key and no monthly bill. Switching is a setting, not a rewrite. Address validation is also enforced server-side — bypassing the widget does not bypass the check.
A Cashier Screen That Actually Wakes You Up
The pending-orders count sits front and centre on the cashier dashboard, pulsing red when there is something to act on. A two-tone chime plays when a new order arrives. Cashiers accept or reject in one click. Rejection asks for a reason, then cascades the cancellation through the sale order, the picking, and the stock reservation. Each pending order shows whether the products are in stock right now — with a warning banner before accept if something is short. The whole screen updates in real time over Odoo bus channels.
Solid Wolt API Plumbing
The integration handles the full two-step Wolt flow: fetch a binding shipment promise, then create the delivery against it. If the promise expires before the cashier accepts, a fresh one is fetched silently and the flow retries. Cancellations go through the proper Wolt cancel endpoint with the cashier reason attached. A simulator wizard fires fake webhook events, signed correctly, so the full pipeline can be tested without waiting for Wolt to push real status changes.
Webhook Handling That Fails Loudly
Webhooks come back signed as HMAC-SHA256 JWTs and the signature is verified before trusting any payload. Twelve event types from order received through order delivered map to picking states. Invalid signatures are logged and rejected. Unmatchable order IDs return 200 so Wolt stops retrying. An admin panel handles webhook subscription management without leaving Odoo.
Numbers That Are Actually Useful
The manager view sits behind the same dashboard, gated by a group. It filters by date range and only counts Wolt Drive orders. Non-Wolt sales never get mixed in.
Acceptance and Rejection Rates
Coloured warning thresholds when rates drift from expected ranges. Average delivery time alongside.
Orders Over Time
A line chart showing order volume by day. Useful for spotting seasonal patterns and planning stock accordingly.
Peak Hours Heatmap
Day-of-week by hour — genuinely useful for staffing decisions and understanding when to have more cashiers available.
Top Rejection Reasons
Pulled from the structured field the reject wizard writes to. No parsing chatter HTML, so the chart is honest.
Top Delivery Localities
Including how many addresses fell outside the delivery zone — the kind of signal that tells you whether opening a second branch makes sense.
Wolt Fees vs Revenue
Total Wolt fees and what percentage of revenue they consume, so the cost of the channel is always visible.
The Details That Matter
A few decisions that shaped how the module holds up in production.
- Address validation runs on the server, not just in JavaScript. Bypassing the widget does not bypass the check — the partner record will not save without a confirmed pin position.
- Rejection reasons are stored on the picking as a real structured field, not buried in chatter HTML that needs regex-stripping later. This is what keeps the analytics chart honest.
- The map provider is a clean abstraction. Adding Mapbox or HERE later is a new class file, not a refactor of existing code.
- Webhooks fail loudly. Invalid signatures are logged and rejected. Unmatchable order IDs return 200 so Wolt does not keep retrying. Everything else is processed and pushed to the dashboard via the bus.
- The simulator wizard fires correctly signed fake events at the webhook receiver, so the full pipeline can be tested without waiting for real Wolt status changes.
Built With
Chosen for reliability, maintainability, and zero unnecessary dependencies.
Need a Delivery Integration
That Actually Works?
We build custom Odoo modules for last-mile delivery platforms, marketplace APIs, and third-party systems. Tell us what you are trying to solve.