Skip to content

Create an API key

POST
/api-keys
curl --request POST \
--url https://example.com/api-keys \
--header 'Content-Type: application/json' \
--cookie bottle.session_token=<bottle.session_token> \
--data '{ "name": "Xero sync", "scopes": [ "tenant:read" ], "expiresAt": "2026-04-15T12:00:00Z" }'

The response carries the key once. Only its hash is stored, so it cannot be shown again. A key may be granted no more than its creator can do, and never the scopes for managing keys.

Media typeapplication/json
object
name
required
string
>= 1 characters <= 80 characters
Example
Xero sync
scopes
required

What this key may do. Never more than its creator may do.

Array<string>
>= 1 items
Allowed values: tenant:read tenant:write customers:read customers:write products:read products:write tax:read tax:write orders:read orders:write rounds:read rounds:write drivers:read drivers:write rota:read rota:write timeoff:write handovers:write deliveries:write cash:read cash:write stock:read stock:write invoices:read invoices:write members:read members:write invitations:read invitations:write keys:read keys:write connections:read connections:write shops:read shops:write billing:read billing:write privacy:read privacy:write accounting:read accounting:write setup:read setup:write emails:read console:read console:write console:owner
expiresAt

Optional. A key with an end date is one nobody has to remember.

string | null format: date-time

Created, with the key

Media typeapplication/json
object
id
required

UUID v7

string format: uuid
name
required
string
prefix
required
string
scopes
required
Array<string>
Allowed values: tenant:read tenant:write customers:read customers:write products:read products:write tax:read tax:write orders:read orders:write rounds:read rounds:write drivers:read drivers:write rota:read rota:write timeoff:write handovers:write deliveries:write cash:read cash:write stock:read stock:write invoices:read invoices:write members:read members:write invitations:read invitations:write keys:read keys:write connections:read connections:write shops:read shops:write billing:read billing:write privacy:read privacy:write accounting:read accounting:write setup:read setup:write emails:read console:read console:write console:owner
createdAt
required
string format: date-time
lastUsedAt
required
string | null format: date-time
expiresAt
required
string | null format: date-time
key
required

The key itself. Shown once: copy it now, we do not store it.

string
Example
{
"id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f",
"name": "Xero sync",
"prefix": "btl_7f3a9c21",
"scopes": [
"tenant:read"
],
"key": "btl_7f3a9c21_XV0m…"
}

Not signed in

Media typeapplication/json
object
error
required
string
message
required
string
Example
{
"error": "not_found",
"message": "Customer not found"
}

Not allowed to manage keys, or asking for a key to do it

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