Getting started
From an email address to a queryable Apache Iceberg catalog in a few minutes, from the terminal or from an agent. Everything here works against https://api.lakehousebox.com today; nothing is described that the service does not do.
What you get
A catalog is one Iceberg REST catalog with its own object storage, run in Nuremberg, Germany, by NewCo SL: it organises your tables and connects them to your tools; LakehouseBox includes the storage and the table maintenance. You bring the engine: DuckDB, PyIceberg or Spark read and write it directly; LakehouseBox is never in the query path. Credentials are per catalog, storage sessions are per table and short-lived, and every tenant is separated at the catalog. (The API calls a catalog a warehouse: /v1/warehouses, warehouse_id; the CLI accepts both words.) The free plan meters one thing, storage: 5 GB. No card.
1. Install the command line
One Python file, standard library only, verified against a published SHA-256. Python 3.9 or newer. No sudo.
curl -fsSL https://lakehousebox.com/install.sh | sh
lhbox --version
Or with pip tooling: pipx install lakehousebox (the package on PyPI follows the same file; until the first release is published there, install from the URL above). The installer puts lhbox in ~/.local/bin and prints a PATH hint if that directory is not on your PATH. The CLI talks to https://api.lakehousebox.com by default; set LHBOX_URL only for a self-hosted or local stack. Details: CLI reference.
2. Connect this machine
One command. The CLI prints a link and a code and waits; open the link, create your account there if you have none (name, email, organisation, a password from the mail), accept the Terms, and approve the connection: this machine's name, the catalog, read and write (you may lower it to read). The CLI receives its own key, saves it to ~/.config/lhbox/credentials.json (mode 0600) and never shows it. Every later command reads it from there; revoke it any time from your account page. The CLI talks to https://api.lakehousebox.com by default; set LHBOX_URL only for a self-hosted or local stack.
lhbox login
# Open https://lakehousebox.com/app/device?user_code=XXXX-XXXX and approve the connection …
# Connected to demo_data (read and write) as laptop. Saved to ~/.config/lhbox/credentials.json.
Without a browser on this machine, the email-code path still works: lhbox signup --email you@company.com --workspace acme, then lhbox signup --email … --code 123456 --accept-terms --save (six digits by mail from no-reply@lakehousebox.com, valid ten minutes). Your first catalog is named demo_data; another is lhbox catalog create <name> (a minute or so; names match ^[a-z][a-z0-9_]{0,62}$). Every command that names a catalog takes the name (or the id) as its positional argument, --catalog <name> as an alias; the destructive ones (catalog delete, catalog publish) also want --confirm (or --yes). Global flags (--json, --human, --url, --api-key) may go before or after the subcommand.
3. Connect your engine
lhbox connect --engine duckdb # or pyiceberg, spark; --catalog <name> when you have several
Prints a paste-ready recipe with the catalog's credential inside. For DuckDB it is four statements; the one that matters is ATTACH 'acme--demo-data' AS demo_data (TYPE ICEBERG, …) with the bare bucket name, <handle>--<catalog> with underscores as hyphens: the s3:// form attaches read-only. The catalog is attached under its own name, so the recipes of two catalogs paste into one session without colliding, and the recipe's example query is a comment so the block pastes whole. Engines exchange the credential for catalog tokens (900 s) and per-table storage sessions themselves. All three recipes and their gotchas: Engines.
4. Load and query
CREATE TABLE demo_data.demo.cities AS SELECT * FROM read_parquet('cities.parquet');
SELECT country, count(*) FROM demo_data.demo.cities GROUP BY 1 ORDER BY 2 DESC;
That is an Iceberg table now: versioned, compacted by the catalog's maintenance, readable by any engine pointed at the catalog. Many files, or CSV files, in one commit: lhbox table import 'data/*.parquet' --namespace demo --name cities (Engines). To choose identifier fields, required columns or partitioning, create the table first with lhbox table create --column id:long:required:identifier … and then INSERT. Check what landed with lhbox table get --catalog demo_data --namespace demo --name cities.
5. Give agents their own keys
lhbox agent create --name reporter --grant <warehouse_id>:write
# Agent reporter created (member of the organisation; grants: demo_data:write). Its API key, shown once: al_live_…
An agent key holds exactly the grants you give it, read or write per catalog (none until granted), is revoked on its own (lhbox agent revoke --agent-id …) and never manages the organisation or its people. Invite colleagues with lhbox org invite --email …; claim your company's email domain with lhbox org domain --domain … so verified colleagues can join.
For agents
Output is JSON whenever stdout is not a terminal; every error is a typed object with a code, a message and usually a remedy; the exit code carries the class (1 fix the input, 2 a real limit or conflict, 3 auth, 4 not found, 5 retry, 6 malformed command). lhbox usage (GET /v1/usage) lists every limit with its headroom so a limit is never met by failing. Every mutation takes --idempotency-key. The whole documentation as one plain-text file: /llms-full.txt; the index: /llms.txt.
Limits on the free plan
| what | value | enforced |
|---|---|---|
| storage, private · public | 5 GB · 50 GB | yes: the one metered thing; bucket quota, and 409 at create and vend time |
| catalogs per project · projects per account | 3 · 5 | yes, at creation |
| tables per catalog · namespaces per catalog | 50 · 10 | no: guideline (engines commit straight to the catalog; enforcement planned) |
| objects | 50,000 | no: guideline, metered hourly |
| catalog operations · commits per month · seconds between commits | 1,000,000 · 20,000 · 10 | no: guideline |
| snapshot retention | 20 snapshots · 7 days | applied by maintenance, not disableable |
Storage is measured hourly by maintenance and summed over the organisation; over the limit, creating catalogs or tables and vending write credentials answer 409 quota_exceeded (reading still works) until space is freed. The guidelines are abuse limits, not prices, and nothing refuses the 51st table today; GET /v1/usage returns every limit with enforced: true|false and how (limits_detail). Paid plans are to be announced.
Not available today
- A Snowflake data path (the catalog integration connects; reading data needs work on both sides).
- Sign in with Google or any social login; accounts are created with your email address (a password set from the signup mail in the browser, a six-digit code in the CLI). A self-hosted deployment may trust its own OpenID Connect issuer instead.
- A full web dashboard. There is /app/, "Your account" (small, for people; agents use the API): log in with email and password (the session stays in the tab), see the organisation's catalogs with your level on each, create one, delete one by typing its name, create tokens for agents with read or write per catalog (the key is shown once), invite and manage members, read usage against the 5 GB, and run SQL with DuckDB compiled to WebAssembly in the browser (the site never sees the data; it talks to the catalog and the object store with your own scoped credentials). It refuses writes as a courtesy, not as a permission; the API and the CLI remain the primary interface.
- An SLA; we publish what we measure instead. One site, daily off-host backups, rehearsed restore.
- Paid plans (waiting for the company registration).
Help
hello@lakehousebox.com. Security reports: security@lakehousebox.com (security.txt). Legal: Terms, Privacy, Acceptable use, Data processing, Security overview, Legal notice.