Permissions
Each business-scoped endpoint requires a resource:action permission.
Sessions use the person’s role. API keys and OAuth connections use their granted
permissions, limited by what their creator was allowed to grant.
| Scope | What it allows |
|---|---|
tenant:read |
See the business and who is in it. |
customers:read |
Read customers, and export them as CSV. |
customers:write |
Add and change customers, and record or remove their marketing consent. |
products:read |
Read what the business sells and its prices. |
products:write |
Change products and agreed customer rates. |
orders:read |
Read orders. |
orders:write |
Take orders and change them. |
rounds:read |
Read rounds, vehicles, and the bases they start from. |
rounds:write |
Plan rounds and change them. |
drivers:read |
See which vehicle each driver usually takes. |
drivers:write |
Change which vehicle a driver usually takes. |
rota:read |
See shifts, time off and cover. A driver sees only their own. |
rota:write |
Run the rota: shift patterns, time off, cover and approvals. |
timeoff:write |
Ask for time off. A driver asks only for their own. |
deliveries:write |
Record delivery outcomes, proof and round departure. |
members:read |
See who works there. |
members:write |
Change what people can do, and remove them. |
invitations:read |
See open invitations. |
invitations:write |
Invite people and cancel invitations. |
keys:read, keys:write |
Manage API keys. Never granted to a key or a connection. |
connections:read, connections:write |
Manage connected apps. Requires a signed-in person. |
shops:read, shops:write |
Connect a shop, pull its catalogue and copy its website into the shop. Never granted to a key or a connection. |
storefront:read |
See the business’s own shop: its settings, the draft, what is live and its addresses. |
storefront:write |
Edit, publish or take down the business’s own shop, upload its pictures and manage its domains. Owners and admins only. |
billing:read |
Read the plan and the invoices Bottle has raised, and what is in the business’s own Stripe account. |
billing:write |
Change the plan. Never granted to a key or a connection. |
privacy:read |
See the retention rules, what is due and what has been erased. |
privacy:write |
Change retention rules and erase customer records. Not available to API keys. |
Money in the API
Section titled “Money in the API”Monetary amounts use integer pence: 5400 means £54.00. Product prices exclude
VAT; check the endpoint’s field descriptions for totals and tax breakdowns.
Bottle currently supports sterling. Shop imports in other currencies are rejected.
The money
Section titled “The money”billing:read is granted like any other scope, and is what an accounting
integration or an assistant answering “what do we pay for Bottle” needs. It
covers the plan, the trial, the renewal date and every invoice, each with a link
to the invoice itself.
Only a signed-in owner can change the subscription. billing:write cannot be
granted to API keys or OAuth connections.
What each role has
Section titled “What each role has”Owners have every scope. Admins have every scope except billing:write.
Drivers can read their assigned rounds and products, record deliveries, manage
their own connections and record round departure and return. They cannot browse
the full customer list, team records or business finances. For van sales,
GET /rounds/{id}/customers provides a limited customer search.
Round access is also restricted by role. Drivers can read and record outcomes
only for their assigned rounds. Requests for another driver’s round return 404.
Role still matters after the scope check. An admin holds members:write but
cannot change an owner, and the last owner cannot be demoted.
Being refused
Section titled “Being refused”{ "error": "missing_scope", "message": "This needs the members:write permission, ..." }missing_scope means the caller lacks the required permission. forbidden
means the permission exists but does not allow this specific action or record.
Some areas start on a bigger plan: rounds and planning, vehicles, the rota and
drivers, cash taken by drivers, regular orders, several yards and delivery partners. Each endpoint
in one of them carries x-plan-area in the OpenAPI document, naming the area:
rounds, vehicles, rota, cash, standingOrders, yards or deliveryPartners.
When the business’s plan does not open the area, the request is refused after the scope check, reading included:
{ "error": "plan_locked", "area": "rounds", "message": "Rounds is not on your plan. It starts on Yard. An owner can move up under Billing."}The refusal is the same for a session, an API key and a connected assistant.
Assistants are not offered tools for a closed area at all. GET /billing
returns features, one true or false for each area, so an integration can
check first. A second base (POST /locations) counts as several yards.
Nothing is deleted when a business moves to a smaller plan. The records come back when it moves up again.