ZUI Cloud
ZUI Cloud is the optional production service layer for ZUI applications. It has three independent modules behind one organization and authentication boundary:
| Module | Contract | Use it when |
|---|---|---|
| Config Store | AppSpec and ViewSpec persistence, immutable versions, ownership, and access grants | Users or teams save customized views or complete app configurations. |
| PDF Export | Server-side ViewSpec rendering with supplied data, state, filters, theme, and page settings | A browser view must become a reliable production document. |
| Scheduled Delivery | Durable recurring or one-shot generation with independent Email, SFTP, and Slack target history | A report must arrive on time and remain explainable after failures or restarts. |
No ZUI Cloud module is required to use the open-source ZUI packages. The Cloud and Cloud Private editions expose the same HTTP contracts. Use the Cloud origin when ZUI operates the runtime, or follow the Cloud Private operations runbook when your platform team must own the data plane, upgrades, backups, and delivery egress.
ZUI Cloud
consumer backend ──▶ shared authentication and organization boundary
│
┌───────────────┼───────────────┐
▼ ▼ ▼
Config Store PDF Export Scheduled Delivery
/v1/configs… /v1/render /v1/schedules…
Choose an operating model
| Question | ZUI Cloud | ZUI Cloud Private |
|---|---|---|
| Who operates Chromium, storage, upgrades, and recovery? | ZUI | Your platform team |
| Who holds application data and enforces business policy? | Your application | Your application |
| Integration contract | HTTPS /v1/* API | The same HTTPS /v1/* API |
| Best fit | Fast adoption and no service operations | Residency, private-network, or operator-control requirements |
Cloud Private changes operational ownership, not the trust boundary. ZUI Cloud stores only what a client sends and does not become the application's identity provider, policy engine, or business-data gateway.
Paid pilot plans
ZUI Cloud is currently offered as a paid pilot on a single-node hosted deployment. Both plans include all three Cloud modules and unlimited users, applications, and saved configurations within the customer's organization.
| Plan | Monthly billing | Annual billing | Included each month |
|---|---|---|---|
| Business | $499/month | $4,990/year | 1,000 render jobs and 100 active schedules |
| Platform | $1,499/month | $14,990/year | 10,000 render jobs and 1,000 active schedules |
Annual subscriptions are charged once per year. The listed render and active schedule allowances are capacity boundaries for the pilot; unlimited users, applications, and configurations do not imply unlimited compute or storage.
This is not yet a horizontally scaled or active-active service. The paid pilot runs one active ZUI Cloud process backed by SQLite and local artifact storage. It therefore does not include multi-node failover, shared durable artifact storage, or zero-downtime guarantees. Customer workloads, backup and restore expectations, and support terms are qualified during onboarding. The Cloud Private operations runbook describes the same current topology and its operational constraints.
First production integration
The console at the service root supports organization creation, sign-in, ZUI Cloud API-key management, usage, render requests, and schedules. A platform owner can also bootstrap through the API:
POST /v1/auth/signup
Content-Type: application/json
{
"email": "platform-owner@example.com",
"password": "a-long-random-password",
"name": "Platform Owner",
"organizationName": "Example Engineering"
}
The response contains a session token prefixed zui_st_. Use that session to
create an organization API key:
POST /v1/api-keys
Authorization: Bearer zui_st_...
Content-Type: application/json
{ "name": "production-backend" }
The secret prefixed zui_pk_ is returned exactly once. Store it in the
consumer backend's secret manager and use a different key for every
environment or independently deployable application. API-key listing retains
only a non-secret hint; rotate a key by creating and deploying a replacement
before revoking the old key.
From the trusted backend, the base JSON client contract is:
type CloudError = {
error: {code: string; message: string; details?: unknown}
}
async function cloud<T>(path: string, init: RequestInit = {}): Promise<T> {
const headers = new Headers(init.headers)
headers.set('Authorization', `Bearer ${process.env.ZUI_CLOUD_KEY}`)
if (init.body) headers.set('Content-Type', 'application/json')
const response = await fetch(`${process.env.ZUI_CLOUD_URL}${path}`, {
...init,
headers,
signal: init.signal ?? AbortSignal.timeout(65_000),
})
const body = await response.json() as T | CloudError
if (!response.ok) {
const failure = body as CloudError
throw new Error(`${failure.error.code}: ${failure.error.message}`)
}
return body as T
}
PDF responses are binary, so use the dedicated example in the PDF Export guide rather than this JSON helper.
Credentials and identity
| Credential | Prefix | Intended caller | Accepted by |
|---|---|---|---|
| Session token | zui_st_ | Console or organization-management client | Organization routes; read-oriented module routes that explicitly allow sessions |
| ZUI Cloud API key | zui_pk_ | Trusted application backend | Config Store, PDF Export, Scheduled Delivery, and module history/usage routes |
Authorization: Bearer ... is preferred. X-API-Key is accepted as a
fallback for an API key. Do not send both.
Config Store and Scheduled Delivery can scope work to an opaque consumer user:
X-ZUI-User-ID: customer-user-42
X-ZUI-Group-IDs: finance-ops,regional-admins
Only a backend that has authenticated the user may construct these headers.
Without X-ZUI-User-ID, an organization API key acts as a service
administrator for those modules. Config Store accepts up to 50 unique group
IDs; each delegated ID is limited to 200 characters. Scheduled Delivery uses
the user ID for ownership and does not apply group grants.
Trust boundary
Call ZUI Cloud from a trusted backend. Do not place an organization API key in browser code. A consuming backend authenticates its own user, enforces its application policies, and then calls the required module.
For Config Store, the backend may delegate an opaque consumer identity. For PDF Export, the backend must resolve and authorize the data before placing it in the render payload. ZUI Cloud does not become the consumer application's identity provider or data-access layer.
The normal request path is:
- The application authenticates its user.
- The application authorizes the requested config, data, action, or report.
- The application resolves only the rows and fields that principal may see.
- The trusted backend calls ZUI Cloud with its organization key and, where applicable, delegated identity headers.
- The application returns a minimized result or artifact to its browser.
Do not proxy arbitrary ZUI Cloud paths, delegated headers, render payloads, or schedule target configurations directly from an untrusted client.
Stable module boundaries
- Shared service concerns live under
/v1/auth,/v1/me,/v1/api-keys, and/v1/organization. - Config Store owns
/v1/configsand its subordinate version and access routes. - PDF Export owns
/v1/render,/v1/requests, and/v1/usage. - Scheduled Delivery owns
/v1/schedules,/v1/deliveries, and signed artifact downloads. - A Config Store version may contain resource references and intentionally configuration-owned static data, but never credentials. Live business data should normally remain outside the document.
- PDF Export receives an authorized snapshot; it does not fetch application data or read a Config Store document implicitly.
- Scheduled Delivery can freeze a supplied artifact definition or call an allow-listed, authenticated application generator for fresh authorized data at execution time. Runs never infer a user's permissions.
This separation keeps the contracts portable. A consumer may resolve the latest config from Config Store and send its view plus authorized datasets to PDF Export, but that composition remains explicit in the consumer's backend. That backend can also register the same composition with Scheduled Delivery, which records every occurrence and target outcome durably.
Shared HTTP behavior
All JSON responses use UTF-8. All JSON errors have one stable envelope:
{
"error": {
"code": "invalid_body",
"message": "The request body is invalid.",
"details": [{"path": "page.scale", "message": "must be between 0.1 and 2"}]
}
}
Unknown JSON fields are rejected on typed request bodies. List limits are bounded server-side; callers must not infer that a bounded response represents unlimited history.
Use error codes, not English messages, for application control flow:
| Status | Meaning | Client behavior |
|---|---|---|
400 | Invalid contract, principal, recurrence, or module input | Do not retry unchanged. Log safe validation details and fix the request. |
401 | Missing, expired, revoked, or unknown credential | Refresh a console session or rotate/fix the backend key. |
403 | Valid credential of the wrong kind, or insufficient known access | Do not retry unchanged. Re-authorize the caller and route. |
404 | Unknown or intentionally undiscoverable organization-scoped resource | Do not reveal whether another user or organization owns the ID. |
409 | Optimistic-concurrency or lifecycle conflict | Reload current state and reconcile; never overwrite blindly. |
413 | Request exceeds the configured body limit | Reduce/minimize the payload; compression is not part of the API contract. |
429 | Organization PDF quota is exhausted | Stop render retries and surface quota state from /v1/usage. |
500 | An accepted operation failed internally | Preserve correlation IDs and retry only where the module guide permits. |
503 | Bounded capacity or a disabled execution runtime | Back off with jitter or route to an operator; do not create a retry storm. |
Set explicit connect and total deadlines in every caller. Retry reads with
bounded exponential backoff. Retry a write only when its module supplies a
safe concurrency or idempotency contract; a lost response does not make an
arbitrary repeated POST safe.
End-to-end composition
A governed saved-report workflow deliberately composes all three modules:
GET config head ──▶ authorize resources and query current data
│
├──▶ POST /v1/render ──▶ return an immediate PDF
│
└──▶ POST /v1/schedules
zui-view-url ──▶ application re-authorizes at each occurrence
Config Store protects and versions the document. The consuming application still enforces policies for resources referenced by that document. PDF Export renders an already-authorized snapshot. Scheduled Delivery either freezes a snapshot or calls an allow-listed application endpoint to regenerate one. No module silently reaches into another module or infers runtime permissions.
Go-live review
- Keep every organization key and provider secret out of browser bundles, specs, logs, and analytics.
- Bind every stored config and schedule to the authenticated consumer principal; exercise cross-user and cross-organization denial tests.
- Handle
409as a merge/reload path, not a generic retry. - Put size, timeout, and concurrency limits on the consumer endpoint before it calls ZUI Cloud.
- Record resource IDs and response correlation headers without recording credentials or complete business datasets.
- Test key replacement and revocation before production.
- For Cloud Private operations, complete the backup/restore, synthetic-monitoring, capacity, and rollback checks in the operations runbook.
Continue with the integration contract for Config Store, PDF Export, or Scheduled Delivery.