Integration reference
Get started
Choose your integration, create the right credentials, and make your first request.
1. Choose your integration
Customer accounts →
Accounts, balances, customers, assignments, and payouts. Uses a system API key owned by an active system Owner or PrimaryOwner.
Bottle counters →
Device license checks, counts, and video uploads. Uses a device license key and counter API key provisioned in system management.
System keys, counter keys, and counter license keys are separate credentials. The steps below create a system API key for customer-account integrations.
2. Create your first system API key
- Sign in to BottleSpeed as an active Owner or PrimaryOwner of the target system.
- Open
/application/{systemSlug}/profileand select the Developer tab. The slug is the system name in your application URL, for examplenorth-buffalo. - Choose Permissions: Read for retrieval or Read-Write if the integration creates or changes records.
- Choose Expiration: Never, 7 days, 30 days, or 90 days.
- Select Generate API key, then Copy API key. The complete secret appears only once. Save it before leaving the result.
- Store it in the integration server’s secret storage. Keep it outside browser bundles, source control, and request logs.
API-key permissions do not grant a system role. Customer-account management still requires the creator’s current active Owner/PrimaryOwner membership. An account-specific Owner role is different. Keys also authorize other system APIs allowed for their creator; they have no account-only scope.
Sign in to BottleSpeed →3. Make your first request
Set SYSTEM_SLUG and API_KEY in your server environment, then request one account page. The base URL is https://bottlespeed.com.
curl --fail-with-body \
"https://bottlespeed.com/api/system/$SYSTEM_SLUG/customer-account?page=1&pageSize=25" \
-H "x-api-key: $API_KEY"An empty system returns:
{
"customerAccounts": [],
"pagination": {
"page": 1,
"pageSize": 25,
"totalItems": 0,
"totalPages": 0,
"hasPreviousPage": false,
"hasNextPage": false
}
}| Field | Type | Details |
|---|---|---|
| x-api-key | request header | Preferred system-key header. Alternatively use Authorization: Bearer <system-api-key>. x-api-key takes precedence if both are present. |
| Content-Type | request header | application/json for requests with a JSON body. |
Follow the customer-account reference for populated response objects, pagination, and writes.
Create an API key
/api/auth/system/{systemSlug}/api-keysCreate a key for the authenticated user in this system. The first key is created through the signed-in application; this HTTP example uses an existing key.
Authentication: Active system session or an existing Read-Write system API key. All active system roles can manage their own keys; customer-account APIs separately require Owner/PrimaryOwner.
Request
POST /api/auth/system/{systemSlug}/api-keys
x-api-key: <existing-read-write-system-key>
Content-Type: application/jsonPath parameters
| Field | Type | Details |
|---|---|---|
| systemSlug | string · required | Slug of the system where the caller is an active member. |
| Field | Type | Details |
|---|---|---|
| permissions | Read | Read-Write · required | Read permits GET requests. Read-Write also permits mutations allowed for the owning user. |
| expiresAt | ISO timestamp | null · optional | Omit or use null for no expiration. Otherwise a future ISO 8601 timestamp with a timezone; an empty string is invalid. |
{
"permissions": "Read-Write",
"expiresAt": null
}Response · 200 OK
{
"apiKey": "<new-secret-shown-once>",
"apiKeyRecord": {
"id": "99999999-9999-4999-8999-999999999999",
"permissions": "Read-Write",
"expiresAt": null,
"createdAt": "2026-09-15T12:00:00.000Z",
"isExpired": false
}
}| Field | Type | Details |
|---|---|---|
| apiKey | string | Full credential, returned only by creation. Store it securely before closing the result. |
| apiKeyRecord | ApiKeyRecord | Metadata. id is used to revoke the key; it is not the secret. |
See response object fields and error responses.
List your API keys
/api/auth/system/{systemSlug}/api-keysList the authenticated user’s keys for this system. Secrets cannot be recovered from this endpoint.
Authentication: Active system session or a Read/Read-Write system API key.
Request
GET /api/auth/system/{systemSlug}/api-keys
x-api-key: <system-api-key>Path parameters
| Field | Type | Details |
|---|---|---|
| systemSlug | string · required | Slug of the system where the caller is an active member. |
Request body: none.
Response · 200 OK
{
"apiKeys": [
{
"id": "99999999-9999-4999-8999-999999999999",
"permissions": "Read-Write",
"expiresAt": null,
"createdAt": "2026-09-15T12:00:00.000Z",
"isExpired": false
}
]
}| Field | Type | Details |
|---|---|---|
| apiKeys | ApiKeyRecord[] | Current user’s key metadata, newest first. Empty when no keys exist. |
See response object fields and error responses.
Revoke an API key
/api/auth/system/{systemSlug}/api-keys/{apiKeyId}Delete one of the authenticated user’s keys in the current system. The secret stops authorizing subsequent requests.
Authentication: Active system session or a Read-Write system API key.
Request
DELETE /api/auth/system/{systemSlug}/api-keys/{apiKeyId}
x-api-key: <read-write-system-key>Path parameters
| Field | Type | Details |
|---|---|---|
| systemSlug | string · required | Slug of the system where the caller is an active member. |
| apiKeyId | UUID · required | apiKeyRecord.id from creation or apiKeys[].id from listing. Must belong to this user and system. |
Request body: none.
A missing, already revoked, or other-user key returns 400 with { "error": "API key not found." }. Keys cannot be edited or renewed. Rotate by creating a replacement, updating the integration, then revoking the old key.
Response · 200 OK
{
"success": true,
"apiKeyId": "99999999-9999-4999-8999-999999999999"
}| Field | Type | Details |
|---|---|---|
| success | boolean | true after deletion. |
| apiKeyId | UUID | Deleted key metadata id. |
See response object fields and error responses.
Response object fields
ApiKeyRecord
Metadata only; the secret and hash are never included.
| Field | Type | Details |
|---|---|---|
| id | UUID | Key metadata identifier for revocation. |
| permissions | Read | Read-Write | Maximum key permission; system role checks still apply. |
| expiresAt | ISO timestamp | null | Expiration instant or null for no expiration. |
| createdAt | ISO timestamp | Creation instant. |
| isExpired | boolean | Whether expiresAt has passed when this response was built. |
Error responses
Check the HTTP status before reading success fields. The examples use fictional data. JSON responses can contain null fields; preserve null rather than treating it as an empty string.
| Field | Type | Details |
|---|---|---|
| 400 | Bad request | Invalid permissions/expiration, invalid key UUID, or a key not owned by this user in this system. |
| 401 | Unauthorized | Invalid, expired, revoked or wrong-system key; inactive membership; insufficient system role; or a write with Read permission. |
| 500 | Server error | Unexpected failure, including malformed JSON. An uncertain write may have completed; reconcile before retrying. |
Ordinary error · 400
{
"error": "API key not found."
}Validation error · 400
{
"error": "ValidationError",
"issues": [
{
"code": "custom",
"path": [
"expiresAt"
],
"message": "Expiration must be in the future."
}
]
}error is a string. Validation responses also contain issues, an array with code, path (field names or array indices), and message; other issue fields depend on the validation rule. Missing records use 400 and authorization failures use 401.