add_app_user
ChatGPTAllow a new e-mail to log in to an app with auth.required; an e-mail already there is refused (nothing existing is changed) – use update_app_user for it. No password is set here: the answer carries setupUrl – a one-time link (7 days) through which the user sets it; give it to the owner to pass on, it is the only way in (knowing the e-mail is not enough). roles: free-form names matched by roles lists in the app config – a user with any listed role passes. role (single) is accepted as a shorthand. Login is free for up to 500 users (each users_10k pack adds 10,000 accounts; other extensions do not change capacity; get_app usage.users has the cap); roles are the user-roles extension: without it (get_app usage.roles) assigning a role fails with a message – relay it, do not sell the extension. Returns the user's id: assign rows to them by storing it in an owner/user column (e.g. vehicles.driver_user_id), then filter those rows with { "$user": true } so the user only ever sees their own.
alter_table
ChatGPTAdd, drop or rename columns of an existing table. index: [column, …] adds an index on columns that already exist (see create_table: index: true), for a table that has grown and filters or sorts by them.
create_endpoint
ChatGPTCreate an HTTP endpoint /x/<appSlug>/<name> bound to one owned app. Its HTTP route can be used by external API clients and, when public, by app visitors subject to the app's sign-in and role checks. A name the app already has is refused; no existing definition is overwritten. This call saves the definition without executing its action. Supported saved action kinds: insert{table,allowColumns (required when public),userColumn?,children?,conflict?,computed?,validate?}, update{table,allowColumns (required when public),userColumn?,computed?,validate?,where?,require?}, delete{table}, duplicate{table,columns,allowColumns?,userColumn?,conflict?,computed?,validate?}, pay{table,payment}, query{source}. Duplicate a table row: action {kind:"duplicate",table,columns:[<stored columns to copy, at least one>],…} on a public endpoint. More about endpoints – duplicate, counters, then steps, e-mail, computed / validate / fill, children, conflict – is in get_app_docs (topics endpoint-duplicate, endpoint-counters, endpoint-then, endpoint-email, endpoint-computed, endpoint-children, endpoint-conflict; card payment start: payments); read the one you need before you use it. update.where + update.require: where (same shape as a block's where; {"$user":true}/{"$today":n} allowed) is ANDed onto the rows the call names – a state guard such as {column:"status",op:"neq",value:"shipped"}. With require:"<message>" the whole write is refused with 409 and that message (nothing written, no then run) unless EVERY named row passed the guard; without require a guarded-out row is silently skipped. Put it on every action whose then moves stock or money, so a double click or two clerks cannot ship/issue the same order twice. userColumn (apps with auth.required): that column is always set to the logged-in app user's id on the server; the client value is ignored and a call without an app session gets 401. Use it for created_by / owner_id instead of a hidden form field. public: true = no API key – EVERY endpoint a block of the app posts to (form, row/bulk action, import, kanban/calendar move, button, pos, shop, picking) must be public: true, the page cannot send a key and gets 401; the app's login (auth.required) still applies to it. A public insert/update (and each of its children) MUST list allowColumns – every column its forms, dialogs, row/bulk actions (their set) and kanban moves send; anything else is refused, so a visitor cannot write a column the form does not show. Otherwise an API key is generated and returned ONCE; callers send it in X-Api-Key.
create_table
ChatGPTCreate a table. "id uuid" and "created_at" are added automatically; do not include them. Types: text, integer, numeric, boolean, timestamp, date, jsonb, uuid, file, serial. A uuid column may set references:<table> to become a foreign key to that table's id, or default: { $random: true } to give every row its own random secret (a token for a public "/stav/:token" link that, unlike id, can be replaced with set: { token: { $random: true } } to revoke the old link). file = uploaded file (photo, document), stored as { id, name, type, size }. serial = auto-incrementing number filled by the database (order / invoice numbers) – never put it in a form. Indexes: created_at and every references column are indexed automatically; set index: true on a column a table block or stat filters (where eq/in/range) or sorts by (order) when the table will hold thousands of rows – status, date, owner, number – not on small lookup tables, every index slows writes a little.
create_webhook
ChatGPTSubscribe an endpoint to send its successful insert, update or delete result to an HTTPS address. Choose only the columns the receiver needs. Private, loopback, link-local and reserved IP addresses are refused. The app must own the webhooks extension. The generated HMAC-SHA256 signing secret is returned once; save it securely. Each endpoint can have up to 10 webhook addresses and each app up to 50.
delete_app
ChatGPTDelete an app (its endpoints too). Data tables are kept.
delete_app_user
ChatGPTRemove an e-mail from an app (and log it out).
delete_endpoint
ChatGPTDelete an endpoint.
delete_file
ChatGPTDelete an uploaded file (metadata and bytes). Rows and app config (a hero, logo or share picture) still referencing it keep a dead link.
delete_rows
ChatGPTDelete rows matching where (required). Returns deleted ids.
delete_webhook
ChatGPTRemove a webhook address from an app. Queued deliveries for this address will be cancelled.
discard_app_draft
ChatGPTDiscard an active visual draft without changing the live app.
drop_table
ChatGPTDrop a table and all its data. Irreversible.
export_app
ChatGPTWhere the owner downloads a full export of an app (their data, e.g. to move elsewhere): one ZIP with app.json (config, endpoints, webhooks), schema.json (tables, columns, relations, formats), users.csv, every table as CSV and the uploaded files in their original format. The download needs the owner signed in to vibee.one in the browser, so the assistant cannot fetch it: give the owner the url (or the dashboard, where every app has an export button).
finish_app_update
ChatGPTMark the update of an existing app as done after its last change (upsert_app, endpoints, color scheme, update_app_draft): pages and draft previews open in browsers drop the "updating" overlay and reload the new version right away. Call it once, after all changes of this edit – not between them, or users see a half-built app. reloaded: false = nothing was pending. warnings = blocks posting to an endpoint that is missing or private – fix them before handing the app over.
get_app
ChatGPTGet an app by slug: name, version, URL, extensions and usage vs. limits (records, fileBytes, users, e-mail credits, roles/domain availability) and an outline of its config – the pages with the block types on them, every other key of config in a line. One page or section in full: get_app_part. The whole config: full: true (large – 80–150 kB for a real app).
get_app_docs
ChatGPTRead built-in static documentation and JSON data formats for app configuration. topic selects a predefined reference section; schema selects a predefined block, configuration field or saved-endpoint data format. Both allowed name lists are exposed in this tool's input schema. With neither, returns the reference index. These entries describe configuration data, not new callable tools. This tool does not execute actions, invoke endpoints, access account records, fetch URLs or modify state. All callable MCP operations are separately registered in tools/list with their own descriptions, input schemas and annotations.
get_app_draft
ChatGPTGet the active visual draft of an app, or null: id, draftVersion (read it before editing), preview URL and an outline of the config. A page or section in full: get_app_part { draft: true }; everything: full: true.
get_app_part
ChatGPTRead one page of an app's config in full (page: its path, e.g. "/clients/:id") or one other key of config (section: "payments", "nav", "schedules", …) – instead of get_app with full: true. draft: true reads the active visual draft (and returns its id and draftVersion) instead of the live app. With neither page nor section it gives the outline.
get_app_stats
ChatGPTAnonymous visit statistics of an app's public pages (page.public) for the last days days (default 30, max 400), today included, days in UTC: totals, views and visitors per day, the 20 most viewed pages (by their config path) and sources (referring site or the link's utm_source). Visitors are counted per day without cookies, so a person coming back on another day counts again; logged-in app users, bots and demo apps are not counted. Without the app's stats extension it returns only how many views were counted in the last 30 days (they are counted anyway, the extension shows them). Use it when the user asks how many people visit their web page, which page is read most, or where visitors come from; for a campaign link, suggest ?utm_source=<name> on the URL.
get_app_version
ChatGPTOne version of an app in full: its name, config and endpoints (API keys are never included). Use it to compare with the current app (get_app, list_endpoints) or to take back only a part of it with upsert_app / replace_endpoint.
get_row_history
ChatGPTThe change history of a table that keeps one (config.history of any app of the account), newest first: for each insert, update and delete the time, the actor ({ type: app_user | visitor | api_key | owner | system, id, label }), the endpoint it came through (via), the columns that changed and their values – before and after for an update (only the changed columns), the whole row as after for an insert and as before for a delete. rowId narrows it to one row (the history of a shift, who moved it and from when to when), actorId to one app user's id, since / until (ISO times) to a period. At most 500 rows (default 50). Tracking is switched on with config.history: [{ table, ignore?, keepDays? }] in upsert_app; the history starts at the first write after that.
insert_rows
ChatGPTInsert one or more rows. Each row is an object of column -> value.
list_app_users
ChatGPTList the users of an app: id, e-mail, roles and whether they already set a password. The id is what row data stores against a user ({ "$user": true } in app configs) – use it to assign rows to a user or to look up who a user_id column belongs to.
list_app_versions
ChatGPTVersion history of an app, newest first (the last 30): rev, time, the operations folded into it (one assistant editing session = one version; "baseline" = the state before the first recorded change, "restore" = a restore), page and endpoint counts and a summary of what changed against the version before. Use it to find the version to go back to, or to see what an earlier edit changed.
list_apps
ChatGPTList the user apps with URLs.
list_color_schemes
ChatGPTList reusable color schemes owned by this account. Schemes can be shared across its apps.
list_endpoints
ChatGPTList endpoints of an app.
list_files
ChatGPTList files uploaded through the user apps (id, name, mime, size, appId, createdAt). Optionally only those of one app. Deleting a row does not delete its file; use delete_file to clean up.
list_request_errors
ChatGPTFailed requests of an app's pages from the last 7 days, newest first: endpoint calls (form saves, row/record/button actions, kanban moves, imports), data loads (target _data), exports, uploads and booking slots. Each has the code shown to the visitor next to the error (requestId), status, the message they saw (error), detail = why the server refused it, for you (missing role, column not in allowColumns, endpoint missing or not public, validate rule, rows not visible to that user, login required, database constraint), the app user's e-mail and the config version the page ran. Pass requestId when the user has the code, target to see one endpoint only. Use it to find why saving or loading fails, then fix the app; do not paste the detail to the app's visitors.
list_tables
ChatGPTList all tables and their columns in the user database.
list_webhook_deliveries
ChatGPTShow up to 100 recent delivery statuses for an app. History is retained for 30 days.
list_webhooks
ChatGPTList webhook addresses and selected columns for one app. Signing secrets are never included.
patch_app
ChatGPTChange an existing app by a list of edits instead of resending its whole config (upsert_app): read the page or section with get_app_part, then send only what changes. Each edit is { op: "replace" | "add" | "remove" | "move", path, value? / from? } with a JSON Pointer into config, e.g. { op: "replace", path: "/pages/~1clients/blocks/0/title", value: "Clients" } ("/" inside a name is written "~1"; an array element may be numbered or named by its path / name / key / id; "add" into an array inserts at the index, "-" appends). The edits apply in order and all or none; the result goes through the same checks as upsert_app, so visual, text and name-only changes are refused here too – use patch_app_draft for those. Returns the same as upsert_app.
patch_app_draft
ChatGPTChange the active draft by a list of edits instead of resending its config (update_app_draft) – the way to make a visual, text or name change. Read the page with get_app_part { draft: true, page }, then send only what changes. Each edit is { op: "replace" | "add" | "remove" | "move", path, value? / from? } with a JSON Pointer into config, e.g. { op: "replace", path: "/pages/~1clients/blocks/0/title", value: "Clients" } ("/" inside a name is written "~1"; an array element may be numbered or named by its path / name / key / id; "add" into an array inserts at the index, "-" appends). The edits apply in order and all or none, then the same rules as update_app_draft hold (data sources, actions, access and PWA settings stay unchanged). Pass expectedDraftVersion from get_app_draft. Call finish_app_update once after the last change of this edit.
publish_app_draft
ChatGPTPublish a reviewed visual draft. Rechecks current app version, dependencies and permissions; a conflict leaves the draft and live app unchanged.
query
ChatGPTRead rows from a table with optional select/where/order/limit (max 1000). where ops: eq,neq,gt,gte,lt,lte,like,ilike,in,is_null,not_null. lookups: [{column, table, label, as}] LEFT JOINs <table> on its id = <column> and returns <table>.<label> as column <as> (usable in select/where/order/group). group: {by: [col | {column, dateTrunc: day|week|month|year, as}] (a dateTrunc bucket is a day / ISO week / month of the APP's config.timezone, a date column its own day), aggregates: [{fn: count|sum|avg|min|max, column?, as}]} returns grouped rows (by columns + aggregates). aggregates: [{table, column, fn, valueColumn?, where?, as}] adds a per-row aggregate over child rows (<table>.<column> = row id), e.g. active loans per book. Instead of a foreign key the rows may be related by match: [{ column: <child column>, parent: <this row's column> }] (equal values: the same employee) and/or overlap: { start, end, parentStart, parentEnd, unit?: "minutes"|"hours" } = the child's timestamp range meets this row's period (a date column is that day's start in config.timezone, the end exclusive): fn "sum" is then the child rows' TIME INSIDE the period, each cut at the period's edges (a night shift across the first of the month counts only its part in it), fn "count" the rows that meet it – OVERTIME: on a period table (employee, od, do, fond_min stored by an endpoint computed work_minutes) add aggregates [{ table: shifts, fn: sum, as: worked, match: [{ column: employee_id, parent: employee_id }], overlap: { start: starts_at, end: ends_at, parentStart: od, parentEnd: do }, where: [{ column: status, op: neq, value: cancelled }] }] and computed [{ as: diff, expr: [worked, "-", fond_min] }, { as: overtime, expr: [diff, "max", 0] }] (a shift's status NULL fails a neq where). A computed that uses an aggregate repeats its subselect per use, fine for a page of periods, not for thousands of rows. PLAN AGAINST ACTUAL: record real time in a table of entries (employee, start, end – a clock-in is a button block / insert endpoint whose set has { start: { $now: true } }, filled by the SERVER at the click; a clock-out an update set: { end: { $now: true } } with where end is_null), then give a plan row (a shift) overlap aggregates over the entries of the same employee: fn sum = the time worked INSIDE the shift, fn min with valueColumn: start = the first arrival, fn max with valueColumn: end = the last departure, fn count = the entries; overlap.openEnd: "now" counts an entry with no end yet (a running timer) up to this moment. computed [{ as: plan, expr: [end, minutes, start] }, { as: missing, expr: [plan, "-", worked] }, { as: late, expr: [first_arrival, minutes, start] }] and a max with 0 for the positive part. The same aggregate on a PERIOD row (overlap against its from / to dates) gives actual hours for payroll next to the planned ones and the fund. CAPACITY against a need: fn "coverage" (needs overlap) is the FEWEST related rows present at once anywhere in this row's period – the row is a need (place, from, to, how many people), the related rows what covers it (the shifts at that place): 8–12 two people and 12–16 one is a coverage of 1, and a gap of an hour in the middle is 0 however many people worked. { table: shifts, fn: "coverage", as: have, match: [{ column: place_id, parent: place_id }], overlap: { start, end, parentStart: from_at, parentEnd: to_at }, where: [{ column: status, op: neq, value: cancelled }] } plus computed [{ as: missing, expr: [wanted, "-", have] }, { as: short, expr: [missing, "max", 0] }] (a where on short gt 0 lists the gaps; negative missing is a surplus); valueColumn is what each related row counts as (0.5 for a half-time person, a seat count). QUALIFICATION: qualified: { table: skills, match: [{ column: employee_id, child: employee_id }, { column: skill, parent: role }], where?: [{ column: valid_until, op: gte, value: { $today: 0 } }] } on ANY aggregate counts only the related rows for which such a row of another table exists – child = a column of the counted row, parent = a column of this row; so a need for a "manager" count…
remove_app_domain
ChatGPTDisconnect an owned app from its custom domain, stopping access through that hostname and clearing its verification token and search-indexing setting. Reconnecting requires setting and verifying the domain again. The app stays reachable on its default platform URL. The domain provider's DNS records are not changed.
replace_endpoint
ChatGPTOverwrite the complete saved definition of an existing HTTP endpoint in an owned app. Fails if the endpoint does not exist. Its method, action and public-access setting take effect for app visitors and external API clients. A private endpoint receives a new API key, returned once, that invalidates the previous key. Later requests to the endpoint can write records, send configured email, trigger attached webhooks or initiate configured payments; replacing the definition does not itself run the action. The same input validation and access rules as create_endpoint apply.
restore_app_version
ChatGPTRestore an owned app's saved name, configuration and HTTP endpoints from an earlier version. The restored pages, access settings and endpoint definitions take effect for public visitors and external API clients; configured outbound actions can affect third-party recipients when later invoked. Restored schedules may resume real writes and outbound email. Same-name endpoints are updated in place, missing ones are recreated, and endpoints absent from that version are deleted with their webhook subscriptions and queued deliveries. A private endpoint keeps its current API key when available. Table data, app users, files and the custom domain are unchanged. Open pages reload and the restore records a new version. Confirm the target version with the user before restoring.
retry_webhook_delivery
ChatGPTQueue a failed delivery for another attempt. Only failed deliveries may be retried.
run_schedule
ChatGPTRun one existing schedule saved in an app owned by the authenticated account, immediately outside its normal time slot. The saved rule selects account-owned source rows and applies its configured steps for each row: insert adds records, update overwrites matching records, delete removes matching records, and email sends messages to the configured recipients. These are real effects, not a preview; sent email cannot be recalled. A once rule records the rows it has handled, including failed rows, so they are not automatically retried; a repeatable rule can repeat its effects. The input identifies the app and saved schedule only; it cannot supply steps, code, URLs or a new operation. Returns processed-row and failure counts and up to five errors, and saves the last-run status. Inspect the saved source and steps with get_app before requesting a run.
set_app_color_scheme
ChatGPTApply a reusable color scheme to an app without replacing its pages or data configuration. Set colorSchemeId to an id from list_color_schemes, or null to return to the default palette.
set_app_domain
ChatGPTServe an app on a hostname the user owns (e.g. "fleet.company.com") with an automatic HTTPS certificate. The result tells which DNS records the user must create at their provider (A/CNAME + a TXT proving they control the domain); pass that on. The domain goes live only after verify_app_domain succeeds. An app has at most one domain: to change it, call remove_app_domain first. Only apps with the custom-domain extension can have one; otherwise the call fails with a message — relay it, do not sell the extension.
set_app_url
ChatGPTChange the readable start of an app's address: "sklad-pohyby-zasob-ae377a69df7e9817.apps.vibee.one" becomes "sklad-ae377a69df7e9817.apps.vibee.one" with words "sklad". The 16 hex digits at the end never change; words are lowercased, diacritics and spaces become plain letters and dashes (max 40 characters). The slug changes with it: use the returned slug in every later call. Old links, QR codes and API calls keep working – they redirect to the new address. A custom domain stays as it is and its app users stay logged in; on the new platform address they sign in once more.
set_app_user_status
ChatGPTSet an app user status: active approves a pending account or unblocks it, blocked suspends access immediately. Both invalidate existing sessions. Does not change roles or password.
start_app_draft
ChatGPTCreate or reopen the one active visual draft of an existing app. The live app stays unchanged. Returns the draft id, draftVersion, a private preview URL for authors and an outline of the config (pages with their block types, sections of config in a line); read a page with get_app_part { draft: true }, or pass full: true for the whole config.
test_action
ChatGPTPreview the validation and permission result of one existing button saved in an app owned by the authenticated account. Identify the saved button by appSlug, page and label; index distinguishes duplicate labels. Supported controls are table row, record, kanban card and bulk actions, and button blocks. This is a diagnostic dry run. The server builds the same request as that saved control using its stored endpoint and configuration, checks its session rules, roles, allowed columns and validation, and rolls back the database transaction including configured follow-up writes. No row changes are committed, no e-mails or webhooks are sent, and no payment session is started. The input cannot define an operation, supply endpoint configuration, select an arbitrary URL or execute code. fields supplies values only for the selected button's saved dialog fields. row or rows selects records visible to the simulated app user; params supplies page URL parameters. as selects an existing app user by email, simulated roles, or an anonymous visitor. Omitted values use the saved control's defaults; an authenticated app defaults to simulated roles of the button, otherwise to an anonymous visitor. Returns the selected button, simulated user, validation or permission status, proposed row changes and email recipients, or the refusal reason. Links and PDF controls are reported without following the link or generating a file. Use when the owner asks to check a saved button or diagnose its failure; this tool does not perform the actual button action.
update_app_draft
ChatGPTReplace the draft name/config with visual and content changes. Existing data sources and actions, access, and PWA settings must stay unchanged. Pass expectedDraftVersion from get_app_draft. The public app stays unchanged. Open previews of the draft show an "updating" overlay until finish_app_update, then reload – call it once after the last update_app_draft of this edit. For a small change prefer patch_app_draft: it sends only the edits. Returns the new draftVersion, not the config.
update_app_user
ChatGPTChange an existing app user (fails for an unknown e-mail – use add_app_user). roles replace the current ones (omit = keep, [] = clear; can take away access to pages guarded by roles), role is a single-role shorthand; password and login are kept. While the user has no password, the answer carries a new setupUrl and the previous link stops working. reset: true clears the password and logs the user out (forgotten password) and returns a new setupUrl for the owner to pass on.
update_rows
ChatGPTUpdate rows matching where (required). Returns updated rows.
upload_image
ChatGPTStore a picture in an app's file storage and get back its FileValue and URL. Give exactly one of content (base64, with or without a data: prefix, max 3 MB) or url (public https link, max 10 MB, fetched by the server). png, jpeg, webp, gif and avif are accepted (checked on the bytes; svg is not). The returned url ("/x/<slug>/_file/<id>") goes straight into hero.image, image.src, section.image, page seo.image, icon or header.logo; the returned file object is the value of a file column (insert_rows) shown with format "image", "gallery" or "carousel". Counts against the app's file limits like any upload. The picture is stored as it is, not resized.
upsert_app
ChatGPTCreate an app or replace the configuration of an existing app in the authenticated account. Omit slug for creation; provide the existing slug and expectedVersion for an update. Returns the saved app URL and validation warnings. Saving takes effect immediately and may publish pages accessible to external visitors or change access settings. Appearance, text or name-only changes to an existing app are rejected; these changes require a private draft and separate publication. get_app_docs topic "core" documents the configuration format; its other predefined topics cover individual components.
upsert_color_scheme
ChatGPTCreate a reusable app color scheme, or update one you own by its id. Updating it overwrites the saved palette and supplied styling, and refreshes all apps using that scheme. Each light/dark palette must contain accent, accentHover, accentSoft, onAccent, background, surface, text, muted and border colors as #RRGGBB. Text contrast is checked on save. Optional style sets the shape and type of the same apps: radius ("none" square corners, "small", "medium" default, "large"), font ("system" default, "humanist", "geometric", "rounded", "serif", "mono" = system font stacks, nothing is downloaded; "geist" modern and technical, "inter" neutral and very legible, "onest" warm, "manrope" geometric, "plus-jakarta-sans" friendly and wide, "nunito" rounded, "source-serif" serif, "geist-mono" monospace = web fonts hosted by Vibee, with full Latin incl. Czech, Slovak and Polish accents), cards ("shadow" default, "border" = a thin outline instead of a shadow, "flat" = neither) and textScale ("small", "normal" default, "large" – every text size at once, for a tablet read from a distance). Left out on an update, style stays as it was; {} resets it. This changes only the visual theme.
verify_app_domain
ChatGPTCheck the TXT record from set_app_domain and, when found, start serving the app on its custom domain. Fails with a message while the record is not visible yet (DNS propagation takes minutes); relay it and retry later.