Appearance
Delivery Settings
Overview
Delivery Settings control whether a location accepts delivery orders and how delivery is priced and bounded. They are not a standalone page: they are the Delivery Settings section inside the Online Ordering configuration screen, stored as part of the location's online ordering settings object.
Key Purpose: Configure the delivery region, delivery fee, and delivery minimum order amount for a location.
Purpose
This section lets you configure the delivery-related parts of online ordering for a location:
- The delivery region — an ordered list of named delivery areas that defines where you deliver and what it costs there.
- The delivery fee model (free, flat charge, or free over a threshold), plus optional distance-based pricing.
- The delivery minimum order amount required before a delivery order can be placed.
Whether delivery is enabled at all (the delivery.enabled toggle), delivery preparation delay (delivery.delay), delivery cutoffs (delivery.same_day_cutoff / delivery.next_day_cutoff), and future-day scheduling (schedule_order_for_future_days.delivery) live in the broader Online Ordering settings — see Online Ordering.
Key Concepts
- Delivery Region (
delivery_region.zones): An ordered list of delivery areas. Each area covers a radius, a driving distance, a set of postcodes or a list of streets, and may carry its own fee or be marked as somewhere you do not deliver. Areas are checked top to bottom and the first one that matches an address decides both coverage and price. See Delivery Region. - Delivery Fee Type (
delivery_fee.type): One of three models —Free delivery,Charge delivery fee for all orders, orFree delivery for orders over a certain amount. - Per-area fee (
delivery_region.zones[].fee): The fee charged when that area is the one that matched. Left blank, the area falls back to the fee rules below. This replaces the old per-postal-code custom-fee list. - On the POS bill: the delivery fee is itemised automatically on Square and Shopcaisse, and is opt-in on MplusKassa, Hendrickx/Vanhoutte and Lightspeed K-Series — see Integrations → Fees and Tips on the POS Bill.
- Distance-Based Pricing (
delivery_fee.distance_pricing_enabled): Optional pricing by driving distance, available whenever the fee type is notFree delivery. It applies to whichever area the order matched when that area leaves its own fee blank. Can betiered(per-distance-band fees) orflat_rate(price per km). - Delivery Minimum Order Amount (
minimum_order_amount): A minimum order value required before a delivery order is eligible.
Actions
Set the Delivery Region
Build the list of delivery areas. Next to "Add area", pick a shape — Radius, Driving distance, Postcodes or Streets — then name the area, fill in what it covers, and optionally give it its own delivery fee. Drag areas into the order you want them checked; the first area that matches an address decides. Mark an area "Do not deliver here" to carve it out, and put it above whatever would otherwise have covered it. Up to 10 areas, at least one of which must be an area you do deliver to. See Delivery Region.
Set the Delivery Fee
Pick the delivery fee type. If it is not Free delivery, enter the base fee (delivery_fee.fee). For Free delivery for orders over a certain amount, also enter the order amount that qualifies for free delivery (delivery_fee.minimum_order_amount_for_free_delivery). To charge different prices in different places, put the fee on the delivery area itself; to price by how far the driver goes, switch on distance-based pricing.
Set the Delivery Minimum Order Amount
Toggle minimum_order_amount.enabled on and enter the required amount (minimum_order_amount.amount).
Location
- Backoffice Route:
/online/online-ordering(nav: Online → Online Ordering, section Delivery Settings,id="DeliverySettings") - Backend Controller:
app/Http/Controllers/Api/BackOffice/OnlineOrderingController.php(show/update) - Save Endpoint:
PUT /back-office/online-ordering/{locationId}— the route group sits inside the/back-officeprefix, and is gated by theedit-online-orderingpermission (the matching read isGET /back-office/online-ordering/{locationId}withview-online-ordering). Validated byapp/Http/Requests/BackOffice/OnlineOrdering/StoreOnlineOrderingRequest.php - Vue Component:
src/views/online/online-ordering/forms/DeliverySettings.vue(mounted insidesrc/views/online/online-ordering/OnlineOrdering.vue)
Fields
Delivery Areas
| Property | Value |
|---|---|
| Field ID | delivery_region.zones |
| Label | Delivery Region |
| Type | Ordered list of delivery areas |
| Default | [] (empty) |
| Validation | nullable array, maximum 10 entries; at least one entry must not be a refusal |
Description: The ordered list that defines delivery coverage and per-area pricing. Each entry carries a name, one shape (radius / distance / postcode / street), an optional fee, and a "do not deliver here" flag. The first area that matches an address decides. Full field reference: Delivery Region.
A location whose list is still empty falls back to its previous single-mode setup (delivery_region.type plus radius / max_distance / postal_codes / streets), read as an equivalent ordered list. Those legacy fields are documented on Delivery Region.
Delivery Fee Type
| Property | Value |
|---|---|
| Field ID | delivery_fee.type |
| Label | Delivery Fee |
| Type | Choice (DeliveryFeeTypes) |
| Default | Free delivery |
| Validation | required, must be a valid DeliveryFeeTypes value |
Description: The delivery fee model. Valid values (from the DeliveryFeeTypes enum):
Free deliveryCharge delivery fee for all ordersFree delivery for orders over a certain amount
Delivery Fee
| Property | Value |
|---|---|
| Field ID | delivery_fee.fee |
| Label | Delivery fee for all other orders |
| Type | Currency (€) |
| Default | 0 |
| Validation | required and numeric when fee type is not Free delivery |
Description: The base delivery fee charged. Not required when the fee type is Free delivery.
Minimum Order Amount for Free Delivery
| Property | Value |
|---|---|
| Field ID | delivery_fee.minimum_order_amount_for_free_delivery |
| Label | The total order amount needs to be over … to qualify for free delivery |
| Type | Currency (€) |
| Default | 0 |
| Validation | required and numeric only when fee type is Free delivery for orders over a certain amount |
Description: The order amount at or above which delivery becomes free. Below it, delivery_fee.fee is charged.
Per-Area Fee
| Property | Value |
|---|---|
| Field ID | delivery_region.zones[].fee |
| Label | Delivery fee (on the expanded delivery area) |
| Type | Currency (€), or blank |
| Default | blank — "Use the default fee" |
| Validation | nullable, numeric, ≥ 0; rejected outright on an area marked "do not deliver here" |
Description: Charging different prices in different places is done here, on the delivery area itself, rather than through a separate override list. The fee comes from the same area that decided coverage, so the two can never disagree. The field is hidden when the fee type is Free delivery.
Blank is not zero. Blank means "fall back to distance pricing or the base fee"; 0 means delivery is genuinely free in that area.
The separate "Custom Fees by Postal Code" list is gone. Per-postal-code and per-street overrides (
delivery_fee.custom_fees) were folded into the delivery areas: each override became an area carrying that price. Once a location has delivery areas, the old list is no longer read when an order is priced, and sending it back is rejected on save. Locations that have not been set up as areas yet keep their old overrides working, read as equivalent areas.
Distance Pricing Enabled
| Property | Value |
|---|---|
| Field ID | delivery_fee.distance_pricing_enabled |
| Label | Route Distance-Based Pricing |
| Type | Toggle |
| Default | false |
| Validation | nullable boolean |
Description: Enables fee calculation based on driving distance. Shown whenever the fee type is not Free delivery — it is no longer tied to a region type. It applies to whichever delivery area the order matched, when that area leaves its own fee blank.
Distance Pricing Type
| Property | Value |
|---|---|
| Field ID | delivery_fee.distance_pricing_type |
| Label | Tiered / Flat Rate |
| Type | Choice (tiered / flat_rate) |
| Default | tiered |
| Validation | nullable string, must be tiered or flat_rate |
Description: How distance-based pricing is computed when distance_pricing_enabled is true.
Distance Fees (Tiered)
| Property | Value |
|---|---|
| Field ID | delivery_fee.distance_fees |
| Label | Rules |
| Type | Array of { max_km, fee } |
| Default | [] (empty) |
| Validation | nullable array (when distance pricing is tiered); each tier requires max_km (numeric, > 0) and fee (numeric, min: 0) |
Description: Per-distance-band fees, e.g. "for routes up to X km, charge €Y". Tiers must increase in distance. If no rule matches, the default delivery_fee.fee is used.
Flat Rate per km
| Property | Value |
|---|---|
| Field ID | delivery_fee.flat_rate_per_km |
| Label | Price per km |
| Type | Currency (€ / km) |
| Default | 0 |
| Validation | required, numeric, min: 0 when distance pricing type is flat_rate |
Description: Price per km of driving route distance. The fee is the rate multiplied by the route distance rounded up to the nearest km (e.g. €1.50/km over 3.2 km = 4 × €1.50 = €6.00).
Delivery Minimum Order Amount Enabled
| Property | Value |
|---|---|
| Field ID | minimum_order_amount.enabled |
| Label | Delivery minimum order amount |
| Type | Toggle |
| Default | false |
| Validation | required boolean |
Description: When on, a minimum order value is required before a delivery order is eligible.
Delivery Minimum Order Amount
| Property | Value |
|---|---|
| Field ID | minimum_order_amount.amount |
| Label | Minimum order amount |
| Type | Currency (€) |
| Default | 10 |
| Validation | required and numeric when minimum_order_amount.enabled is true |
Description: The minimum order value required for delivery when the toggle is enabled.
Business Rules
- The delivery fee type comes from the
DeliveryFeeTypesenum and is exactly one of:Free delivery,Charge delivery fee for all orders, orFree delivery for orders over a certain amount. - When the fee type is
Free delivery, no fee fields are required; the base fee, the per-area fee and distance-based pricing are all hidden/skipped. delivery_fee.minimum_order_amount_for_free_deliveryis required only when the fee type isFree delivery for orders over a certain amount. Above that threshold the order qualifies for free delivery; below it the basedelivery_fee.feeapplies.- The delivery fee is resolved in one order: the matched delivery area's own fee (including
0) → distance-based pricing, if enabled → the basedelivery_fee.fee. Free delivery and free-over-a-threshold are settled against the order total before any of that. - Per-area fees replace the old
delivery_fee.custom_feeslist. Once a location has delivery areas,custom_feesis not read when an order is priced and is rejected on save. - Distance-based pricing (
delivery_fee.distance_pricing_enabled) is available whenever the fee type is notFree delivery; it is no longer gated on a region type. It is eithertiered(per-band fees indistance_fees) orflat_rate(price per km inflat_rate_per_km). Beyond the widest tier no rate is configured, so the basedelivery_fee.feeapplies rather than nothing. - Tiered distance rules must be in increasing distance order: each tier's
max_kmmust be greater than the previous tier'smax_km, and fees cannot be negative. - The delivery region is an ordered list of up to 10 delivery areas, at least one of which must be an area you deliver to. Each area needs a name and a value for its shape. See Delivery Region.
- The delivery minimum order amount (
minimum_order_amount.amount) is only required whenminimum_order_amount.enabledis true. - This
minimum_order_amountis the delivery minimum and is separate from the pickup minimum (pickup_minimum_order_amount); see Online Ordering.
FAQs
- What delivery fee options are there? Three: free delivery, a flat charge on all orders, or free delivery only when the order is over a set amount (otherwise the base fee applies).
- How do I decide where I deliver? Build a list of delivery areas under Delivery Region. Each area is a radius, a driving distance, a set of postcodes or a list of streets, and the first one that matches an address decides. See Delivery Region.
- Can I charge different fees in different areas? Yes. Put the fee on the delivery area itself — that is what per-area fees are for. Leave an area's fee blank for it to use your default fee. You can also price by driving distance instead, with tiered bands or a flat price per km.
- Where did "Custom Fees by Postal Code" go? Those overrides now live on the delivery areas. A postcode you used to price separately is simply an area with that postcode and that fee. Nothing was lost — existing overrides keep applying until the location is set up as areas.
- How does the free-delivery-over-amount option work? You set a qualifying order amount. Orders at or above it ship free; orders below it are charged the base delivery fee.
- How is the per-km flat rate calculated? The route distance is rounded up to the nearest km and multiplied by the per-km rate (e.g. €1.50/km over 3.2 km = 4 × €1.50 = €6.00).
- Is the delivery minimum separate from the pickup minimum? Yes. The delivery minimum is
minimum_order_amount; pickup has its ownpickup_minimum_order_amount. - Where do I turn delivery on or set delivery prep time and cutoffs? Those are in the broader Online Ordering settings (
delivery.enabled,delivery.delay,delivery.same_day_cutoff/next_day_cutoff), not in this section — see Online Ordering.
Relations
Depends On
- Locations: Delivery settings are stored on the location's online ordering settings object.
- Online Ordering: Delivery enable/disable, prep delay, cutoffs, and future-day scheduling live there.
Affects
- Online Ordering storefront: Region, fee, and minimum determine delivery availability and pricing at checkout (storefront behavior not verified here).
Related Features
Examples
The delivery settings are stored as part of the online ordering settings object. The shapes below match StoreOnlineOrderingRequest validation and the Constants::$DEFAULT_ONLINE_ORDERING_SETTING defaults.
Free delivery, one radius area
json
{
"delivery_region": {
"zones": [
{ "id": "a1", "name": "Delivery area", "shape": "radius", "radius": 10, "exclude": false, "fee": null }
]
},
"delivery_fee": {
"type": "Free delivery",
"minimum_order_amount_for_free_delivery": 0,
"fee": 0,
"distance_pricing_enabled": false,
"distance_pricing_type": "tiered",
"distance_fees": [],
"flat_rate_per_km": 0
},
"minimum_order_amount": {
"enabled": false,
"amount": 10
}
}Flat Charge on All Orders + Delivery Minimum
json
{
"delivery_region": {
"zones": [
{ "id": "a1", "name": "Delivery area", "shape": "radius", "radius": 8, "exclude": false, "fee": null }
]
},
"delivery_fee": {
"type": "Charge delivery fee for all orders",
"fee": 3.5
},
"minimum_order_amount": {
"enabled": true,
"amount": 15
}
}Free Delivery Over a Threshold
json
{
"delivery_fee": {
"type": "Free delivery for orders over a certain amount",
"minimum_order_amount_for_free_delivery": 25,
"fee": 3.5
}
}Two postcodes priced differently
Each priced postcode is its own delivery area. Anything not covered by an area is not delivered to at all.
json
{
"delivery_region": {
"zones": [
{ "id": "a1", "name": "1012", "shape": "postcode", "postal_codes": ["1012"], "exclude": false, "fee": 3 },
{ "id": "a2", "name": "1013", "shape": "postcode", "postal_codes": ["1013"], "exclude": false, "fee": 6 }
]
},
"delivery_fee": {
"type": "Charge delivery fee for all orders",
"fee": 4.5
}
}Driving-distance area with tiered distance pricing
The area leaves its fee blank, so the tiers price the order.
json
{
"delivery_region": {
"zones": [
{ "id": "a1", "name": "Delivery area", "shape": "distance", "max_distance": 12, "exclude": false, "fee": null }
]
},
"delivery_fee": {
"type": "Charge delivery fee for all orders",
"fee": 5,
"distance_pricing_enabled": true,
"distance_pricing_type": "tiered",
"distance_fees": [
{ "max_km": 5, "fee": 3 },
{ "max_km": 10, "fee": 5 }
]
}
}Driving-distance area with a flat rate per km
json
{
"delivery_region": {
"zones": [
{ "id": "a1", "name": "Delivery area", "shape": "distance", "max_distance": 12, "exclude": false, "fee": null }
]
},
"delivery_fee": {
"type": "Charge delivery fee for all orders",
"fee": 5,
"distance_pricing_enabled": true,
"distance_pricing_type": "flat_rate",
"flat_rate_per_km": 1.5
}
}