Start
The console
The console is where people who build with dabadata sign in, switch between workspaces and projects, copy keys, manage their app's users and their team, and change the plan. It lives at /console/ and calls the same HTTP API your app calls, as you.
Open it
Go to dabadata.com/console/ and create an account: an email and a password, an email link, or Google. Your first sign-in sets up a workspace named after your email and a first project, my-first-app, so there is something to look at straight away. Getting started walks from there to a live row in your own page; Accounts and teams covers sign-in, sessions and invitations.
A self-hosted server serves the console at /console/ too, once inspect/ is built. The older viewer keeps working at / with ?token=<view token>.
Workspaces and projects
The top bar, left to right: the dabadata wordmark, the workspace switcher (the workspace's name with a pill for its plan: Free, Starter, Pro, Scale or Enterprise), a /, the project switcher, the live / test switch (two small pills, live and test), a Docs link and your avatar (Account settings, Documentation, the theme and Sign out). The sidebar is in two groups: the first is headed with the chosen project's name and holds the project's pages, which act on one environment of that project; the second, Workspace, holds the pages that act on the whole workspace.
- A workspace is your team: its members, its plan and its projects. Everything a plan limits (connections, storage, projects, members) is counted per workspace. Create another one from the workspace switcher (+ New workspace); see the workspace cap. The switcher's menu shows each workspace's plan and your role in it, as
Free - owner. - A project is one app, with a live and a test environment (Projects and keys). Developers and up create projects from the project switcher (+ New project): from the To-do starter (a
taskstable and its rules), Empty (rolesadminandmember, no tables), a curated template or one saved in the workspace. The new project's four keys are shown once, in a dialog that closes only after you tick that you stored the secret keys. - The URL says where you are:
/console/<workspace id>/<project id>/<page>, with_testafter the project id for the test environment, and/console/<workspace id>/<page>for a workspace page. Links can be shared with anyone in the workspace.
Live and test
The live / test switch in the top bar decides which environment every project page shows and changes. On test the test pill is amber and an amber strip under the top bar says "Test environment - its own data, keys and trace. Nothing here touches live." The two share nothing but the project: test has its own tables and rows, its own keys (pk_test_..., sk_test_... against pk_live_..., sk_live_...), trace, logs, users, allowed origins and secrets. A change you make on test never reaches live, and the Overview, Logs and Users pages count each environment on its own.
Work on test first. Apply a definition to live when it is ready; nothing is copied from one to the other by itself.
Project pages
In the sidebar's order. Each acts on the environment the switch shows.
Overview
Today's numbers (UTC) as of when the page opened (the Refresh button in the header reads them again; the console does not poll) in four tiles: Connections now, Requests today (your app's calls, not the console's own), Denied today (calls your rules refused, red above 0) and Errors today (red above 0). Under them Plan usage (this month, every project of the workspace), Last errors and the Project card with what your app needs to reach this environment: the project id, the API URL, the environment, the region. On a new account's first project, developers see Get your secret keys until both secret keys have been shown (each is shown once). Until your app writes its first row, a three-step Get started card shows: copy your keys, paste the snippet, and "Waiting for your app's first write". It turns into "Your app is live" when a row arrives from a real caller (not the console, not the secret key).
Definition
The project definition - tables, roles, rules, views, storage, identity and the mcp block - as JSON in definition.json, with Check (a dry run: Valid - N change(s) to apply, or N problem(s) with the path of each), Apply..., + Insert table, + Insert view, every earlier version with its diff, and Roll back to this. Applying only adds tables and columns; one you removed stays in the database and shows as Drift. The Drift panel beside the editor resolves each item - Drop..., Rename into... a declared table or column, Convert to ... for a type that differs - always as a dry run first, with the rows that would block a conversion; and when a check shows a new table or column beside a leftover, it offers the rename that keeps the rows. It is the console's face of PUT /v1/schema, POST /v1/schema/migrate and its versions.
Tables
The rows of every table with filters (or a SQL where) and sort, live. Insert a row, edit a cell, delete a row, export CSV; at most the first 1,000 rows, use SQL for more. You act as the console: the rules are bypassed and every change is in the trace as bypass, with your account as the user. A strict table (access: "views") has a lock and the badge views only: your app's users reach it only through views and actions.
Files
The files your app's users uploaded to this environment, live, bucket by bucket (File storage). On top, the workspace's file storage against the plan and the largest file allowed. Each bucket shows its file count, its size and its read, write and delete rules; open one for its files with a filter, a preview and the details of each, a link to open it (signed for 5 minutes unless the bucket is public), and delete (developers and up). Uploads that were started but never completed show as pending and are removed after an hour. Buckets are declared in the definition's storage block; with none yet the page shows a block to start from. Every bucket is also the read-only table files_<bucket>.
Sites
Static sites (HTML, CSS, JS, images) of this environment, at <name>.dabadata.site and, from Starter, at your own domains (Sites). Developers and up create a site (the name is its address and cannot change; Single-page app answers index.html for a path with no file), roll back to an earlier deploy, connect a domain, which then shows the DNS records to add, and Move to live (or Move to test) a site with its name and files (Move a site). With no site yet the create form is open; once there is one it is a New site button below the sites. Open a deploy's row to see its files; on the live deploy each opens on the site. Each site with a live deploy shows its Readiness: a badge (reachable, propagating, unreachable) and, per public hostname, whether DNS, TLS, the route, the deploy and (for a domain) the certificate pass, with the reason for any that fails; Check now runs the check again. The page does not upload: a deploy comes from the CLI (dabadata sites deploy ./dist --site <name>) or the MCP tool site_deploy. The item is hidden when the server has sites off.
SQL
A query editor on this environment's schema. Read mode (the default, every role) runs as a database role that can only SELECT. Write mode (developers and up, after typing the project id) turns the editor red and first runs your statements as a preview that is rolled back, shows what they did, and commits only when you press Commit within 5 minutes. Statements stop after 10 seconds, and at most 1,000 rows per statement come back. Writes made here bypass the rules and are not pushed to live subscribers until they reconnect. Save queries you use often by name. The routes are POST /v1/sql and the ones after it.
Trace
Every call with its decision and the rule that made it, live, filtered by user, table, operation, decision and time. Open a row for the explanation, the rule and the before-and-after diff, or "Simulate as another user" to see what the same call would have done for someone else. See Trace.
Logs
Three tabs, live: API (every request with its route, status, duration, credential and user), Realtime (sockets connecting, subscribing, being refused, and each change fanned out) and Errors (server errors and rejected input, grouped by route). Kept for the plan's API log retention.
Rules
The rules as a matrix of tables and operations (read, create, update, delete), with column rules folded under their table, and a simulator: as this role and user, on this row, at this time, is this allowed, and which rule decided. Nothing is written and nothing is traced. A cell that says nobody has no rule: no end user may do it. See Rules.
Views
Every view of the definition (Views): its base table, its allow and rows rules, joins, params, columns, computed fields, what callers may filter and sort, and a Shape per role table. Run as reads the view as any user with its params, filter, sort and limit; it is a real read that lands in the trace, and a refusal shows the 403 that user would get. With no views, developers get Add a sample view.
Playground
The to-do demo, always on this project's test environment, even with the switch on live: sign in test users with different roles, open two frames side by side and watch your own rules decide. It needs a tasks table with title and done; developers get a button that adds the starter's table to the test definition. Minting the test users' tokens needs developer or higher.
Apps
This environment as an MCP server, so your coding agent can build the app with it and people can use the app inside ChatGPT and Claude (Build with an AI agent):
- MCP server:
onoroff(it is on when the definition has"mcp": { "enabled": true }; developers get a button that adds the block), and the server's URL,https://dabadata.com/mcp/<project id>(with_testfor test). - Connect a client: the ready line for Claude Code (
claude mcp add ...), the.cursor/mcp.jsonfor Cursor, and the connector URL for ChatGPT and Claude, which sign people in with the environment's hosted accounts ("Sign-in is off" while those are off). - Build it with your agent: a prompt to paste into your agent, with the
.envlines it needs (the secret key is left for you to fill in from Keys). - Widgets: which table draws which widget in a chat (the built-in
table,formandrecord, or one of your own), and the custom widgets stored in this environment, with a preview. - Start from a template: curated starting points (a definition with its rules, the
mcpblock and widgets); developers make a new project from one.
Authentication
How your app's own users sign in, and who they are once they do (Sign-in for your app's users, Identity and tokens). Four tabs; everything they change is saved as a new version of this environment's definition. The older Users and Identity pages are now its last two tabs, and their addresses lead there.
- Sign-in methods: Email and password and Magic link, on whenever hosted accounts are; and the social providers Google, Apple, Microsoft, GitHub, GitLab, Discord, LinkedIn and Slack. Each opens Set up <provider>: the callback URL to register at the provider, the steps there, and the client id and client secret (kept encrypted as the project secret
<PROVIDER>_CLIENT_SECRET). A provider isOn,Needs setup(configured, but hosted accounts are off or its client secret is missing) orOff. See Sign in with Google, Apple and more. - URL configuration: App URLs first - every address your app runs at, each set as an allowed origin (CORS) and a redirect URL in one step, with a Add localhost and 127.0.0.1 button for a dev server's port (a browser treats the two as different sites). A row shows whether its origin is allowed and which redirect URLs it has; removing it takes it out of both lists. Both writes refuse a list that changed elsewhere meanwhile. Below: the address of the hosted sign-in page (
/auth/<environment id>/), Sign-up (Open or Invite only, which closes sign-up through the social providers too), Verify email addresses, and the Redirect URLs list on its own (absolute, exact, at most 20). - Third-party tokens: the four ways in and which are on (a provider's JWT, tokens your backend mints, anonymous, hosted accounts), the trusted issuers of the definition, Add a provider, which turns a client id into the exact issuer block for Google, Apple, Clerk, Auth0, Firebase Auth or Supabase Auth for you to paste into the definition (it saves nothing), and a link to Secrets, where project secrets now live.
- Users: the accounts of your app's own users (not the workspace's members): search, Add user (with a password or an emailed link), change a role, disable, delete. On test, tick users (or none, for all) and Copy to live: each gets a live account and an invitation mail to choose a password; passwords are not copied (Copy users to live). Each shows how they sign in and a status:
active,invited(has not chosen a password yet; Resend invite mails a new link),unverified(the email is not confirmed) ordisabled. - Test inbox (test environment only; developers and up): every mail the environment sent your app's users - confirmations, sign-in links, resets, invitations - with each link's state (unused, used, expired). Open or copy a link, copy a broken one, make it expired or used to try your app's error handling, empty the inbox, and switch off sending test mail to real inboxes (The test inbox).
While hosted accounts are off, every tab but Third-party tokens shows "Hosted accounts are off for the <env> environment"; developers turn them on with one button (open sign-up, emails verified, new people get the default role).
Keys
The project id, the API URL and both environments' keys. Copy the publishable key; the secret key shows only its first characters, because it is shown in full once, when it is made. The environment the top bar is on comes first; the other one is folded below. Rotate publishable key and Rotate secret key each ask first, then make a new key and keep the old one working for 24 hours (shown as rotated - stops ...; a new secret key is shown once, in the dialog); Revoke stops a key at once (revoking the only key of a kind makes its successor and shows it once). Lost the secret key? Rotate it. A key labelled site key belongs to a connected WordPress site. Restricted keys, under the current environment's keys, lists the restricted keys (name, role, prefix, last used) with New restricted key (a name and the role it acts as; the key is shown once), Rotate and Revoke for developers and up. The Snippets tab has ready-to-run code for plain HTML, Vite / React / Vue, a Node backend, WordPress and curl, built from this environment's real keys and its first table.
Secrets
Your own API keys and other values a definition names but must not contain, stored encrypted on the server, never shown again and separate for live and test. AI provider keys has a row each for Anthropic (Claude), OpenAI and Google Gemini: paste the key and it is saved as ANTHROPIC_KEY, OPENAI_KEY or GEMINI_KEY for an action's ai block to name; a saved row shows when it was set, with Replace and Delete. Other secrets takes any name and value: a shared JWT signing key, a sign-in provider's client secret, a webhook URL, or an AI key under a name of your own. Use one shows an action that calls Claude with the stored key. Developers and up see and change secrets; other roles see why not.
Workspace pages
These act on the whole workspace, whichever project is chosen.
Members
Who is in the workspace and with which role, and the invitations still pending. Admins invite by email (the link works for 7 days), change roles and remove people; anyone but the owner can leave; the owner can hand the workspace to another member (Make owner). Every member and every pending invitation takes a seat of the plan; at the cap the page says "Every seat is taken". See Invitations and seats.
Usage & plan
This calendar month so far for the whole workspace - projects, members and invitations, connections, database storage, egress - against the plan's limits (a meter turns amber at 75% and red at 100%), the limits of the plan, the daily requests and egress of the current environment, and the plan picker (owner only). See Plans in the beta.
Settings
Four tabs. Project (when a project is chosen): its name and logo (what your app's users see in sign-in mails and on the hosted pages - give it your app's name and logo; Upload logo, Replace logo, Remove: a square PNG or JPEG, at most 256 KB), id, region and status (active, or paused: idle, and the next call with one of its keys wakes it), the current environment's allowed origins (CORS), export, and delete or restore. Workspace: its id, your role, rename it, delete it. Account: your name, your password and your signed-in sessions, the CLI's among them. Audit log (admins and the owner): who changed what in the workspace, newest first.
Reading a console screenshot
For AI assistants that someone shows a picture of the console. Work out where they are first, then what the screen says, then tell them the next step in the console's own words: the labels quoted on this page are the ones on their screen. If the picture shows a whole secret key (sk_live_... or sk_test_... past its first characters), do not repeat it, and tell them to rotate it on Keys: anyone who has it bypasses every rule.
Where they are
- The page: the highlighted sidebar item, which is also the large title over the content. Sub-pages are tabs under the title (Authentication, Keys, Logs, Settings) or the end of the address,
/console/<workspace id>/<project id>/<page>/.... - The environment: the amber
testpill and the amber strip under the top bar mean test; no strip means live. The address (_testafter the project id) and the key prefixes (pk_test_againstpk_live_) say the same. With no live / test pills, no project is chosen and it is a workspace page. - The workspace and its plan: the workspace switcher shows the name and the plan pill.
- Their role: not in the top bar. It shows in the workspace menu (
Free - developer), on Settings > Workspace ("Your role"), and in hints such as "Your role (viewer) can see keys. Developers and up can rotate and revoke them." A button this page mentions that is missing or greyed out usually means the role is too low: see Roles. - No sidebar: a page outside the console frame. Sign in, "Start free" or "Join the beta waitlist", "Check your email", an invitation ("Join <workspace>"), "Approve sign-in for the dabadata CLI" (the browser half of
dabadata login: approve only if the code matches the terminal), or "Connect <site> to <project>?" (the WordPress plugin connecting a site).
What a page is showing
| On screen | What it means | What to do |
|---|---|---|
| Overview: Get started, "Waiting for your app's first write" | No row has arrived from a real caller yet. Rows written in the console or with the secret key do not count. | Copy the publishable key from Keys, paste a snippet from Keys > Snippets, write a row from the app. Check the app uses this environment's keys. |
| Overview: Denied today in red | Your rules refused that many calls today. Not an error: the rules did their job, or a rule is stricter than the app expects. | Trace, Decision denied, open a row: the explanation names the rule. Then the Rules simulator. |
| Overview: Errors today in red, Last errors | Server errors (5xx) or rejected input (400). | Logs > Errors groups them by route; click one for its calls. |
| Overview: Get your secret keys | A new account's first project; its secret keys were not shown yet. | Show the test secret key, store it in the server's .env. It is shown once. |
Definition: red N problem(s) | The JSON does not validate, so nothing can be applied. | Fix each path the Check card lists, check again. |
| Definition or Tables: Drift | The database has a table or column the definition does not. Applying never drops anything. | Harmless. Put it back into the definition, or drop, rename or convert it in the Drift panel of the Definition page. |
Definition: amber unsaved changes | The editor differs from the stored version; nothing is in force yet. | Check, then Apply... |
Tables: lock, views only | A strict table: end users read it only through views and write it only through actions. The console sees every row. | Expected. To change what users see, change the views. |
| Tables: "<table> has no rows yet" or "No tables yet" | Nothing written here, or no table declared, in this environment. | Check the live / test switch first; then the Definition. |
Files: pending | An upload was started but not completed. | Nothing; it is removed after an hour. |
| Files: "No buckets yet" | The definition has no storage block. | Add the block shown on the page and apply. |
Sites: paused, disabled, suspended | Asleep with its idle environment / over the workspace's plan (visitors see "This site is over its plan") / taken down by us. | A deploy or keyed call wakes it / change the plan / contact us. |
Sites: a domain pending or failed | The DNS record is not seen yet, or is wrong. | Add the record shown at the DNS host; the server checks every 5 minutes, or press Check now. |
| SQL: a red editor, "Write mode" | The statements can change any row past every rule. Each run is a rolled-back preview. | Commit within 5 minutes to keep it, or Discard. |
| SQL: "Postgres refused the query" | A SQL error, with line, column and the Postgres code. | Fix the statement. Read mode cannot write: use write mode (developers). |
Trace: allowed, denied, bypass, a red error | A rule let it through / a rule refused it / the secret key or the console, rules not checked / the call failed. | Open the row for the explanation and the rule; "Simulate as another user". |
| Trace: "No calls yet" | Nothing has called this environment. | If the app has run, it most likely uses the other environment's keys: flip the switch. |
Rules: a cell that says nobody | No rule for that operation: no end user may do it. | Add the rule in the Definition. |
| Views: "Denied (403)" | The view's allow rule refuses that user; the app would get the same 403. | Change the user, or the view's allow. |
Apps: off | The definition has no "mcp": { "enabled": true }; the MCP address answers 404. | Turn it on in the definition, check, apply. |
| Authentication: "Hosted accounts are off for the <env> environment" | dabadata keeps no accounts for this app's users here. | Turn on hosted accounts (developers), or bring your own tokens (Third-party tokens). |
Sign-in methods: Needs setup | The provider is configured, but hosted accounts are off or its client secret is missing. | Open it and paste the client secret, or turn hosted accounts on. |
Users: unverified / disabled | The email is not confirmed yet (with Verify email on, no password sign-in until it is) / the account may not sign in. | They open the mailed link / Enable. |
Keys: rotated - stops ... | An old key that still works until then. | Put the current key in every app and server before it stops. |
Keys: a secret key as sk_..•••• | Secret keys are shown once, when made. | Lost it: Rotate secret key (the old one works 24 more hours). |
| Members: "Every seat is taken" | Members plus pending invitations fill the plan's seats. | Withdraw an invitation, remove someone, or the owner changes the plan. |
| Usage & plan: an amber or red meter | 75% / 100% of the plan's limit this month. | See Plans and limits for what happens at the limit. |
Usage & plan: on request in the beta, requested | Pro and Scale are switched on by us; the request is in. | Wait for our email. |
Settings: status paused | The environment was idle and sleeps. | Nothing: the next call with one of its keys wakes it. Console calls do not. |
| "<project> is being deleted" | Deleted less than 7 days ago; both environments answer "project deleted". | An admin restores it on Settings > Project. |
| "This workspace is not here" / "This project is not here" | A wrong id, or they are not a member (or signed in with another account). | Check the account in the avatar menu; ask for an invitation. |
| "Set a password (optional)" | The account signs in by email link or Google only. | Optional: Settings > Account. |
Messages that pop up
Errors show as red toasts at the bottom right, or as a red box in the dialog. The common ones:
| Message | What it means |
|---|---|
| "Your role in this workspace may not do that." | 403 forbidden: the role is too low. An admin or the owner changes roles on Members. |
| "Your plan does not allow more of this. Change the plan on Usage & plan." | 403 plan_limit: projects, seats, storage or workspaces are at the cap. Delete something, or change the plan. |
| "The workspace uses more than that plan allows: ..." | 409 over_limit on moving down a plan. Delete a project or remove someone first. |
| "Project limit reached" | In New project: the plan's projects are used up. |
| "This project is being deleted. Restore it under Settings to use it again." | See the row above. |
| "You are signed out. Sign in again." | The session ended or was revoked. |
| "Too many attempts. Try again in ..." | Rate limited; wait. |
| "The server had a problem (5xx). Try again in a moment." | A server error. If it stays, contact us. |
| "Request failed (<status> <code>)." | An error without its own words; look the code up in the HTTP API reference. |
What people often get wrong
- The wrong environment. The app writes with test keys and they look at live, or the other way round: the rows seem missing. Compare the key prefix in the app with the switch.
- The console is not the app. Tables, SQL and the console bypass the rules, so a write that works here may be denied for the app's users. Ask the Rules simulator, Views' Run as, or the Playground.
- Denied is not an error. A denial is a rule deciding; it is in the Trace with its explanation, not in Logs > Errors.
- SQL writes are quiet. Live subscribers see them only after they reconnect.
- Applying never drops. A table or column taken out of the definition stays in the database and shows as drift, until you drop it in the Drift panel.
- The mails say "my-first-app". Sign-in mails and hosted pages carry the project's name and logo, not the site's; rename the project and add a logo in Settings > Project > General. Until then Overview, Authentication and Sites show "Your app's users will see "my-first-app"".
- The secret key stays on a server. Never in browser code, a chat connector or a screenshot; the publishable key is the one for the browser.
Roles
Everyone in a workspace has one role, the same in every project of it. Each role may do everything the roles below it may:
| Role | May |
|---|---|
viewer | Look at everything: rows, the definition and its versions, the trace, logs, the overview, usage, users, keys (publishable in full, secret by prefix), members. Run read-only SQL and the rules simulator. Not: read secret names, export, or change anything. |
developer | Change the project: insert, edit and delete rows, apply and roll back definitions, write SQL, rotate and revoke keys, set secrets and allowed origins, manage the app's users, mint user tokens, export. Create projects. |
admin | Run the team: invite people, change roles, remove members (not another admin), revoke invitations, rename the workspace, restore deleted projects, read the audit log. |
owner | Exactly one per workspace. Change the plan, transfer ownership, delete projects and the workspace, change or remove admins. |
A button your role may not use is hidden or disabled, and the API answers the same thing: 403 forbidden with an explanation such as your role in this workspace (viewer) may not apply definitions - that needs developer or higher.
Plans in the beta
The plans and their limits are on Plans and limits and the pricing page. During the beta:
- Self-service up to Starter. The owner moves a workspace between Free and Starter on Usage & plan, at once.
- Pro and Scale on request. Their button says Request; we switch them on. The API answers an owner who asks for them with 403
plan_requires_approval. A workspace we put on Pro or Scale stays there, and its owner can still move it down. - Nothing is billed. The plan is recorded; you hear from us before billing starts.
- Moving down is refused while the workspace uses more than the smaller plan allows (projects not being deleted, members plus pending invitations): 409
over_limitwith what is over. Delete a project or remove someone first. - Enterprise is arranged with us, not picked in the console.
The workspace cap
An account may own at most 3 workspaces that are not deleted, the one made at sign-up included. Creating a fourth answers 403 { "error": "plan_limit", "limit": "workspaces", "message" }; delete one or ask us for more. Workspaces you are only a member of do not count, and becoming the owner of one by a transfer is never refused. A self-hosted server sets the cap with DABADATA_MAX_WORKSPACES_PER_ACCOUNT and the highest self-service plan with DABADATA_BETA_MAX_PLAN (default starter).
How it talks to the API
The console has no back door. It signs in with a session cookie and calls the public routes with three extras: the cookie, the header X-Requested-With (without it the cookie is ignored, which stops other sites from using your session), and X-Project: prj_... (or prj_..._test) to name the environment. The server checks that you are a member of the project's workspace and then calls you the console identity:
- Inside the project it is service-level: the rules are bypassed, and every call is in the trace with decision
bypass, sourceconsoleand your account as the user (role: "console", your email as the name).consoleis therefore a reserved role name. - Your workspace role limits what it may do, as in the table above.
- Console sockets do not count toward the plan's connections, console calls and sockets do not count as requests (so Requests today is your app's traffic), and console calls do not wake a paused environment. Their bytes still count as egress.
- Signing out, or revoking the session, closes the console's live sockets at once.
Every route, with its credentials and errors, is in the HTTP API reference.