Skip to Content
Odoo  ·  Wolt Drive Integration

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.

Map-Confirmed Address
Real-Time Cashier Alerts
HMAC Webhook Verification
Manager Analytics

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.

Odoo Python OWL jQuery SCSS Chart.js Leaflet Nominatim Wolt Drive API Google Maps Platform JWT (HS256) WebSocket / Longpolling

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.