Skip to content

Create a round

POST
/rounds
curl --request POST \
--url https://example.com/rounds \
--header 'Content-Type: application/json' \
--cookie __Host-bottle.session_token=<__Host-bottle.session_token> \
--data '{ "roundDate": "2026-04-15", "vehicleId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "driverUserId": "example", "startLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "endLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "yardId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "orderIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "departsAt": "07:30", "notes": "example" }'

Leave out the orders and every unassigned order wanted that day inside the driver’s patch is taken. The stops are put in the best order the router can find, and the round says whether that was roads or straight lines.

Media typeapplication/json
object
roundDate
required
string format: date
vehicleId

UUID v7

string | null format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
driverUserId
string | null
startLocationId

UUID v7

string | null format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
endLocationId

UUID v7

string | null format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
yardId

UUID v7

string | null format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
orderIds
Array<string>
<= 200 items
departsAt
string | null
/^([01]\d|2[0-3]):[0-5]\d$/

Example

07:30
notes
string | null
<= 2000 characters

Planned

Media typeapplication/json
object
id
required

UUID v7

string format: uuid
roundDate
required
string format: date
vehicleId
required

UUID v7

string | null format: uuid
vehicleName
required
string | null
driverUserId
required
string | null
driverName
required
string | null
startLocationId
required

UUID v7

string | null format: uuid
endLocationId
required

UUID v7

string | null format: uuid
yardId
required

UUID v7

string | null format: uuid
status
required
string
Allowed values: planned out done
issuedAt
required
string | null format: date-time
sentOverLimit
required
object
byKg
required
integer | null
> 0
byLitres
required
integer | null
> 0
sentBy
required
string | null
note
required
string | null
sentOverLimitReason
required

Use sentOverLimit.note.

string | null
salesRoom
object
stops
required
integer
seconds
required
integer
lines
required
Array<object>
object
productId
required
string
quantity
required
integer
> 0
cylinders
required
integer
usualCylinders
required
integer
kg
required
number
litres
required
number
heldOrders
required
integer
stillThere
required
boolean
loadConfirmedAt
required
string | null format: date-time
van
required
object
latitude
required
number
>= -90 <= 90
longitude
required
number
>= -180 <= 180
seenAt
required
string format: date-time
distanceMetres
required
integer | null
durationSeconds
required
integer | null
departsAt
required
string | null
/^([01]\d|2[0-3]):[0-5]\d$/
fit
required
object
loadKg
required
number | null
payloadKg
required
integer | null
loadLitres
required
integer | null
volumeLitres
required
integer | null
unweighedItems
required
integer
totalSeconds
required
integer | null
departsAt
required
string | null
/^([01]\d|2[0-3]):[0-5]\d$/
backAt
required
string | null
/^([01]\d|2[0-3]):[0-5]\d$/
shiftEnd
required
string | null
/^([01]\d|2[0-3]):[0-5]\d$/
over
required
Array<string>
Allowed values: weight volume hours doorsShut
geometry
required
string | null
routedBy
required
string | null
notes
required
string | null
deliveryWindowHours
required
Any of:
number
Allowed values: 1
stops
required
Array<object>
object
accountAccess
object
unpaidInvoices
required
boolean
newOrdersBlocked
required
boolean
deliveriesBlocked
required
boolean
id
required

UUID v7

string format: uuid
orderId
required

UUID v7

string format: uuid
transferId

UUID v7

string | null format: uuid
transferLeg
string | null
Allowed values: collection drop
loadLocationId

Set on a stop that collects the round’s own stock from one of your yards: cylinders kept there rather than where the van loads. It has no order and no transfer; orderId carries the stop’s own id.

string | null format: uuid
collectFrom
object
usualYardId
required

UUID v7

string format: uuid
usualYardName
required
string
locationId
required

UUID v7

string | null format: uuid
address
required
object
name
required
string | null
line1
required
string
city
required
string | null
postcode
required
string
sequence
required
integer
> 0
addedAt
string format: date-time
addedOnRoad
boolean
latitude
required
number | null
longitude
required
number | null
placement
string
Allowed values: drop door street postcode none
pin
object
latitude
required
number
longitude
required
number
etaSeconds
required
integer | null
etaAt
required
string | null
/^([01]\d|2[0-3]):[0-5]\d$/
serviceSeconds
required
integer | null
waitSeconds
required
integer | null
outsideHours
required
boolean
proof
required
object
kind
required
string
Allowed values: signature left_safe
signedBy
required
string | null
note
required
string | null
url
required
string
createdAt
required
string format: date-time
lines
required
Array<object>
object
orderLineId
required

UUID v7

string format: uuid
productId
required

UUID v7

string format: uuid
productName
required
string
quantity
required
integer
> 0
deliveredQuantity
required
integer
cancelledQuantity
required
integer
faultySwap
boolean
collect
required
Array<object>
object
productId
required

UUID v7

string format: uuid
productName
required
string
quantity
required
integer
> 0
fulfilment
required
string
Allowed values: delivery collection
paymentMethod
required

On_account: billed later, nothing to collect. link: a payment link raised in the accounting system. cash: the driver takes it at the door.

string
Allowed values: on_account link cash
billingOwner

Bottle: Bottle owns invoicing and payment. shop: the connected shop owns both, so Bottle must only fulfil the order. elsewhere: the business invoiced or took payment outside Bottle, so Bottle only fulfils the order.

string
Allowed values: bottle shop elsewhere
amountDuePence
required
integer
cashTakenPence
required
integer
paidAt
required
string | null format: date-time
leaveInstruction
required
string | null
Allowed values: none neighbour safe_place
leaveDetail
required
string | null
shortfallReason
required
string | null
Allowed values: not_on_vehicle damaged refused other
issue
required
string | null
Allowed values: wrong_product access complaint other
issueNote
required
string | null
completedAt
required
string | null format: date-time
failedAt
required
string | null format: date-time
failureReason
required
string | null
Allowed values: nobody_in no_access refused customer_cancelled wrong_day wrong_address nothing_to_leave price_problem payment_problem other
failureNote
required
string | null
customerName
required
string | null
customerPhone
string | null
customerContactName
string | null
customerContacts
Array<object>
object
id
required

UUID v7

string format: uuid
name
required
string
email
required
string format: email
phone
required
string | null
/^\+?[\d\s()-]{7,20}$/
kind
required
string
Allowed values: normal billing both
relationship
required
string | null
<= 60 characters
customerReference
string | null
driverNotes
string | null
customerNotes

The same as driverNotes, for apps before 1.2.8. Never the customer record’s notes.

string | null
deliverTo
required

Name, address and postcode in one line.

string | null
summary
required
string
orderStatus
required
string
Allowed values: placed delivered cancelled
onVan
Array<object>
object
stopId
required

UUID v7

string format: uuid
yardId
required

UUID v7

string format: uuid
yardName
required
string
lines
required
Array<object>
object
productId
required

UUID v7

string format: uuid
productName
required
string
quantity
required
integer
onVanAt
required
string format: date-time
version
required
string
createdAt
required
string format: date-time
updatedAt
required
string format: date-time

Example

{
"id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"vehicleId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"startLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"endLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"yardId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"status": "planned",
"departsAt": "07:30",
"fit": {
"departsAt": "07:30",
"backAt": "07:30",
"shiftEnd": "07:30",
"over": [
"weight"
]
},
"deliveryWindowHours": 1,
"stops": [
{
"id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"orderId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"transferId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"transferLeg": "collection",
"loadLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"collectFrom": {
"usualYardId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"locationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"
},
"placement": "drop",
"etaAt": "07:30",
"proof": {
"kind": "signature"
},
"lines": [
{
"orderLineId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"productName": "19kg propane"
}
],
"collect": [
{
"productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"productName": "19kg propane"
}
],
"fulfilment": "delivery",
"paymentMethod": "on_account",
"billingOwner": "bottle",
"leaveInstruction": "none",
"shortfallReason": "not_on_vehicle",
"issue": "wrong_product",
"failureReason": "nobody_in",
"customerContacts": [
{
"id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"phone": "07700 900123",
"kind": "normal",
"relationship": "Accounts"
}
],
"summary": "3 × 19kg propane",
"orderStatus": "placed"
}
],
"onVan": [
{
"stopId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"yardId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"lines": [
{
"productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"
}
]
}
]
}

Not signed in

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Not a member, or without the permission this needs

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Not found

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Validation failed

Media typeapplication/json
object
error
required
string
Allowed values: validation
message
required
string
issues
required
Array<object>
object
path
required
string
message
required
string

Example

{
"error": "validation",
"issues": [
{
"path": "email",
"message": "Invalid email"
}
]
}