REST API
The DollarBox REST API lets you manage containers, volumes, orgs, members, and kubectl credentials from scripts, CI, or the Terraform provider. Everything the dashboard lets an owner or admin do for these resources, the API can do too.
The API is versioned in the URL. The current version is v1, served under:
https://app.dollarbox.dev/api/v1/
Breaking changes ship under a new version prefix (/api/v2/); v1 stays stable for existing integrations.
Get a token
The API authenticates with personal API tokens.
- Open Account → API tokens in the control panel (https://app.dollarbox.dev/settings/api-tokens/).
- Click Create token, give it a name, and choose a scope:
- Read-only —
GETrequests only. - Read & write — full access for the token's user.
- Read-only —
- Optionally restrict the token to a single org, and optionally set an expiry.
- Copy the token shown on the next screen. It is displayed only once. If you lose it, revoke it and create another.
If your account has two-factor authentication enabled, you'll be asked to re-authenticate before a token is created.
Send the token as a bearer credential on every request:
curl -H "Authorization: Bearer dbx_xxxxxxxxxxxx_..." \
https://app.dollarbox.dev/api/v1/containers/
Tokens carry the permissions of the user who created them, constrained by the org's role. Writes additionally require the token's write scope. Revoke a token any time from the same page; revoked or expired tokens are rejected immediately.
Roles
Every membership in an org has one of three roles. The dashboard and the API enforce the same rules, so a member is refused the same actions with a browser session as with a token.
| Role | Can |
|---|---|
| owner | Everything: containers, volumes, namespaces, billing, backups, team, kubectl credentials, referrals and closing the org. Only an owner can grant or revoke the owner role. |
| admin | Everything an owner can, except referrals, enabling kubectl mode, closing the org and changing who is an owner. |
| member | Read-only: view containers, volumes, logs, status, the billing overview and the kubectl reference page. Members cannot create, change or delete anything. |
Invite someone as a member when they need visibility without the ability to change or delete resources, and promote them to admin when they need to operate the org.
Choose an org
Most resources belong to an org. The API resolves the target org in this order:
- The token's org, if it was created as org-scoped.
- An explicit org slug, via the
X-Dollarbox-Orgheader or the?org=<slug>query parameter. - Your only org, if you belong to exactly one.
If you belong to several orgs and don't specify one, write requests return an org_required error.
curl -H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "X-Dollarbox-Org: my-org" \
https://app.dollarbox.dev/api/v1/containers/
Resources
| Resource | Path | Operations |
|---|---|---|
| Containers | /api/v1/containers/ | list, create, read, update, delete |
| Volumes | /api/v1/volumes/ | list, create, read, delete |
| Namespaces | /api/v1/namespaces/ | list, create, read, reallocate, delete |
| Orgs | /api/v1/orgs/ | list, read, update |
| Members | /api/v1/members/ | list, read, change role, remove (only an owner can grant or revoke the owner role) |
| Invitations | /api/v1/invitations/ | list, read, create, revoke |
| kubectl credentials | /api/v1/kubectl-credentials/ | list, read, create, revoke |
| Snapshot protection | /api/v1/namespaces/{id}/volumes/{pvc}/snapshot-policy/ | read, enable/update, disable |
| Snapshots | /api/v1/namespaces/{id}/volumes/{pvc}/snapshots/ | list, create, read, delete, restore |
| Backup protection | /api/v1/volumes/{id}/backup-policy/ and /api/v1/namespaces/{id}/volumes/{pvc}/backup-policy/ | read, enable/update, disable |
| Backups | /api/v1/volumes/{id}/backups/ and /api/v1/namespaces/{id}/volumes/{pvc}/backups/ | list, create, read, delete, restore |
A complete, machine-readable description lives in the OpenAPI schema. Browse the full reference — every operation, with field-level request and response detail — here, no sign-in required:
- API reference: /docs/api-reference/
The same schema is served live from the control panel for signed-in users (handy for scripts that pull the spec at runtime):
- Schema: https://app.dollarbox.dev/api/v1/schema/
- Interactive docs (Swagger UI): https://app.dollarbox.dev/api/v1/docs/
Provisioning is asynchronous
Creating a container or volume returns immediately with a status of pending; provisioning happens in the background. Poll the resource until its status settles:
- Containers:
pending → provisioning → running(orfailed). - Volumes:
pending → provisioning → bound(orfailed).
# Create a container
curl -X POST https://app.dollarbox.dev/api/v1/containers/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "web", "image": "nginx:1.27"}'
# Poll until it is running
curl https://app.dollarbox.dev/api/v1/containers/123/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN"
A container's name is fixed once created — change other fields in place, but recreate the container to rename it. Volumes are immutable once created; delete and recreate to change size.
kubectl credentials
If an org has kubectl mode enabled, you can issue your own kubeconfig over the API. The kubeconfig (with a freshly bound token) is returned only in the create response:
curl -X POST https://app.dollarbox.dev/api/v1/kubectl-credentials/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "X-Dollarbox-Org: my-org"
Namespaces
By default an org runs in a single Kubernetes namespace. If you build a multi-tenant product on DollarBox, you can carve out isolated child namespaces under the same account — one per end customer, say — each with its own NetworkPolicies, quota, and PodSecurity boundary.
Capacity is one pool: the containers and storage you pay for. Each namespace reserves a slice of that pool via allocated_containers and allocated_volume_gb; the platform namespace gets whatever is left over. The sum of all child allocations may not exceed your paid capacity (you'll get a 409 allocation_exceeded otherwise). New namespaces start at zero allocation, so creating one costs nothing until you move capacity to it.
# Create an isolated namespace with 1 container slot + 5 GB of storage
curl -X POST https://app.dollarbox.dev/api/v1/namespaces/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"slug": "family-smith", "allocated_containers": 1, "allocated_volume_gb": 5}'
# Reallocate capacity in place
curl -X PATCH https://app.dollarbox.dev/api/v1/namespaces/42/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"allocated_containers": 2}'
Provisioning is asynchronous (pending → provisioning → active, or failed); poll the resource until status settles. The read-only k8s_namespace field is the real namespace name (org-<id>-<slug>). The slug is fixed once created — recreate to rename. Deleting a namespace tears it down (cascading volumes, load balancers, and secrets) and returns its allocation to the pool.
Volume snapshots
Snapshot protection is explicitly enabled per Longhorn PVC. The add-on costs €0.10 per protected source GB per month, excl. VAT.
# Enable daily protection and retain seven successful snapshots
curl -X PUT https://app.dollarbox.dev/api/v1/namespaces/42/volumes/homeserver-data/snapshot-policy/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"retention_days": 7}'
# Create the one permitted manual snapshot
curl -X POST https://app.dollarbox.dev/api/v1/namespaces/42/volumes/homeserver-data/snapshots/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "before-upgrade"}'
# Restore a ready snapshot into a new PVC
curl -X POST https://app.dollarbox.dev/api/v1/namespaces/42/volumes/homeserver-data/snapshots/$SNAPSHOT_ID/restore/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"pvc_name": "homeserver-data-restored"}'
Policy, snapshot, and restore operations are asynchronous. Poll their corresponding GET endpoint until it reaches active, ready, or bound. Disabling a policy is also asynchronous because billing continues until the retained CSI snapshots have been deleted.
Volume backups
Off-site backups are enabled per volume and cost €0.15 per backed-up source GB per month, excl. VAT. They are the off-site counterpart to snapshots: snapshots stay in the same storage cluster, backups are shipped to separate storage hardware. See Volume backups.
Unlike snapshots, backups have two endpoint families — one for control-panel volumes (/volumes/{volume_id}/...) and one for PVCs in a child namespace (/namespaces/{namespace_id}/volumes/{pvc_name}/...). The bodies are identical; only the restore target differs.
# Enable nightly backups on an org volume, keeping 14 of them
curl -X PUT https://app.dollarbox.dev/api/v1/volumes/7/backup-policy/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"retention_days": 14}'
# Same thing for a PVC in a child namespace
curl -X PUT https://app.dollarbox.dev/api/v1/namespaces/42/volumes/homeserver-data/backup-policy/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"retention_days": 14}'
retention_days accepts 1 to 30 and defaults to 7. It is the number of successful nightly backups kept, not a wall-clock window. The policy response carries billed_gb and monthly_cost_cents so you can show the cost before committing to it.
# List backups for a volume
curl https://app.dollarbox.dev/api/v1/volumes/7/backups/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN"
# Take the one permitted manual backup
curl -X POST https://app.dollarbox.dev/api/v1/volumes/7/backups/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "before-upgrade", "labels": {"reason": "upgrade"}}'
Only one live manual backup per policy: delete the existing one before taking another. Nightly backups are managed for you and do not count against that.
Restores always create a new volume — the source is never modified, and in-place restore does not exist. The two families differ here: an org volume restores into a new control-panel volume by name, a namespace PVC into a new PVC.
# Restore an org volume's backup into a new volume
curl -X POST https://app.dollarbox.dev/api/v1/volumes/7/backups/$BACKUP_ID/restore/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"volume_name": "homeserver-data-restored"}'
# Restore a namespace PVC's backup into a new PVC
curl -X POST https://app.dollarbox.dev/api/v1/namespaces/42/volumes/homeserver-data/backups/$BACKUP_ID/restore/ \
-H "Authorization: Bearer $DOLLARBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"pvc_name": "homeserver-data-restored"}'
The restore is carved from your pre-paid storage pool at the backup's original size, so the pool needs that much unused capacity or you get a 409. Restores cannot resize.
Policy, backup and restore operations are all asynchronous. Poll the corresponding GET until it reaches active, ready or bound. Disabling a policy is asynchronous too, because the charge continues until the retained backups have actually been deleted from the target.
Backups cannot be managed from kubectl: tenant credentials hold no volumesnapshots permissions, and the platform takes the snapshots on your behalf.
Pagination
List endpoints use cursor pagination:
{
"next": "https://app.dollarbox.dev/api/v1/containers/?cursor=cD0y",
"previous": null,
"results": [ ... ]
}
Use ?limit= to set the page size and follow the next URL (or its cursor) to page forward.
Errors
Errors use a stable envelope. The code is a machine-readable string you can switch on; it won't change without a version bump.
{
"error": {
"code": "quota_exceeded",
"message": "This would exceed your plan's limit of 5 containers. You are using 5.",
"detail": { "resource": "containers", "limit": 5, "current": 5 }
}
}
Common codes include authentication_failed, permission_denied, not_found, validation_error, quota_exceeded, allocation_exceeded, rate_limited, and api_disabled.
Rate limits
Requests are rate limited per token. When you exceed the limit you'll get a 429 with a Retry-After header (in seconds) and the rate_limited error code. Back off and retry after the indicated delay.
Terraform
The official Terraform provider is built on this API — declare your containers, volumes, namespaces, and org membership as code. A namespace's slug is ForceNew (changing it recreates the namespace), while allocated_containers and allocated_volume_gb update in place. (Provider availability is tracked separately; until it ships, the API above is the supported integration surface.)