Skip to content

Record a stop outcome

PUT
/rounds/{id}/stops/{stopId}
curl --request PUT \
--url https://example.com/rounds/019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f/stops/019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f \
--header 'Content-Type: application/json' \
--cookie __Host-bottle.session_token=<__Host-bottle.session_token> \
--data '{ "outcome": "delivered", "reason": "nobody_in", "note": "example", "driverNote": "example", "proof": { "kind": "signature", "signedBy": "example", "note": "example", "image": "example" }, "items": [ { "orderLineId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "quantity": 1 } ], "shortfall": "not_on_vehicle", "cashTakenPence": 1, "empties": [ { "productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "quantity": 1 } ], "issue": "wrong_product", "issueNote": "example", "extras": [ { "productId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "quantity": 1 } ], "cylinders": { "delivered": [], "collected": [], "exception": { "reason": "unreadable", "note": "example" } }, "workReport": { "cylinders": [], "customerSignature": "example", "customerName": "example", "driverSignature": "example", "purchaseOrder": "example", "emailTo": { "mainContact": true, "contactIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ] }, "emails": [] }, "occurredAt": "2026-04-15T12:00:00Z" }'

Delivered marks the order delivered and records when. Where fewer items went than were ordered, a shortfall reason is required and decides what happens to the rest: not_on_vehicle and damaged leave it owed to be planned again, refused writes it off with a refund recorded, other leaves it for the office. Failed records why on the stop and leaves the order standing. Pending undoes either. Where more went than was ordered, or extras name a product that was not on the order, the order grows to match at the customer’s own rate, and any invoice or payment link standing against the old figure is voided; not on an order already paid. Only on a round that has left, and a driver may only do this on their own round. Unpaid invoices alone do not stop delivery. An explicit customer restriction blocks delivery while invoices remain unpaid.

id
required

UUID v7

string format: uuid

Example

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

UUID v7

stopId
required

UUID v7

string format: uuid

Example

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

UUID v7

Media typeapplication/json
object
outcome
required
string
Allowed values: delivered failed pending
reason
string
Allowed values: nobody_in no_access refused customer_cancelled wrong_day wrong_address nothing_to_leave price_problem payment_problem other
note
string | null
<= 500 characters
driverNote
string | null
<= 2000 characters
proof
object
kind
required
string
Allowed values: signature left_safe
signedBy
string | null
<= 120 characters
note
string | null
<= 500 characters
image
required

A PNG or JPEG data URL. Signatures are PNG, photographs JPEG.

string
<= 4000000 characters /^data:image\/(png|jpeg);base64,[\d+/A-Za-z]+={0,2}$/
items
Array<object>
<= 100 items
object
orderLineId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
quantity
required
integer
shortfall
string | null
Allowed values: not_on_vehicle damaged refused other
cashTakenPence
integer | null
<= 1000000
empties
Array<object>
<= 100 items
object
productId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
quantity
required
integer
issue
string | null
Allowed values: wrong_product access complaint other
issueNote
string | null
<= 500 characters
extras
Array<object>
<= 50 items
object
productId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
quantity
required
integer
> 0 <= 1000
cylinders
object
delivered
Array<object>
default: <= 100 items
object
productId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
serials
required
Array<string>
<= 200 items
collected
Array<object>
default: <= 100 items
object
productId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
serials
required
Array<string>
<= 200 items
exception
object
reason
required
string
Allowed values: unreadable not_listed other
note
string | null
<= 300 characters
workReport
object
cylinders
Array<object>
default: <= 200 items
object
side
required
string
Allowed values: delivered collected
productId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
serial
string | null
>= 1 characters <= 100 characters
jobTypeId

UUID v7

string | null format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
checks
Array<object>
default: <= 50 items
object
checkId
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f
answer
required
string
Allowed values: ok problem
note
string | null
<= 500 characters
photo

A PNG or JPEG data URL. Signatures are PNG, photographs JPEG.

string | null
<= 2000000 characters /^data:image\/(png|jpeg);base64,[\d+/A-Za-z]+={0,2}$/
customerSignature

A PNG or JPEG data URL. Signatures are PNG, photographs JPEG.

string | null
<= 500000 characters /^data:image\/(png|jpeg);base64,[\d+/A-Za-z]+={0,2}$/
customerName
string | null
<= 120 characters
driverSignature

A PNG or JPEG data URL. Signatures are PNG, photographs JPEG.

string | null
<= 500000 characters /^data:image\/(png|jpeg);base64,[\d+/A-Za-z]+={0,2}$/
purchaseOrder
string | null
<= 100 characters
emailTo
object
mainContact
required
boolean
contactIds
required
Array<string>
<= 50 items
emails
Array<string>
default: <= 3 items
occurredAt

When it happened, by the device’s clock. Left out, now.

string format: date-time

The round as it now stands

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"
}

That round has not left yet, the order is paid and cannot take extras, or the round has no driver to hold the cash (cash_needs_driver): give the round a driver, then record it again

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"
}
]
}