Data and security
This page collects, in one place, the answers people usually have to extract piecemeal: what is stored where, who can see it, what leaves the platform, how long it is kept — and, in its own section, what does not exist. Three things here depend on the plan: how long run history is kept (7 days on free), the size of the team (one seat for an invited member on top of the owner on free — see Team and roles), and which publication channels are available (web chat only on free — see Plan limits). Roles, data scoping and secrets are not plan-gated and work on any plan.
What is scoped to a workspace
The workspace is a data boundary, and the boundary is drawn in storage rather than in the interface. Every query carries the workspace id, so an object from a neighbouring workspace is not merely hidden — it is not found.
| Data | Scope | Who can read it |
|---|---|---|
| Workflows, versions, runs, logs | workspace | any member |
| Files and storage | workspace | any member |
| Database collections | workspace | any member |
| Knowledge bases and their vectors | workspace | any member |
| Chat history | workspace | any member |
| Agent memory and variables | workspace | this workspace's workflows |
| Secrets | workspace | names — editor and above; values — nobody |
| Connections | workspace | members see the settings, secret fields masked |
| Credit balance, plan, profile | owner's account | the account owner |
A practical consequence: the platform cannot move data between workspaces. If clients must be kept apart, split them into workspaces up front rather than “once we grow”.
Inside one workspace there are three roles deciding who reads and who changes; the breakdown is in Team and roles. One point is worth repeating here: a viewer reads all of the data — chat history, files, collection contents. The role limits changes, not curiosity.
Secrets
A secret is a “name → value” pair belonging to the workspace: Settings →
Secrets. Any template refers to it as {{ secret.NAME }}, so the
name has to be a valid identifier — like an environment variable: OPENAI_API_KEY,
CRM_TOKEN.
How it works:
- Stored encrypted. The value sits in the database as ciphertext; the encryption key is derived from the installation’s master key and is not the key that signs login tokens.
- The value never comes back out. The API returns only the name and a “value is set” flag. Neither an admin, nor the owner, nor support can look at a stored secret — it can only be overwritten. When editing, an empty value field means “keep the current one”.
- Decrypted once per run. The first
{{ secret.* }}in a run loads and decrypts the set into process memory for the duration of that run; nothing decrypted touches disk. - A workspace admin changes secrets, while an editor can see the names (needed for autocomplete in the editor). A viewer sees not even the names: the list of names is a map of your integrations.
- Deleting a secret does not break the graph on the spot. A reference to a deleted secret expands to an empty string and the workflow keeps running — with an empty key in the header. The failure arrives from the remote service and reads like “invalid key”, not like “no such secret”. Which is exactly why deleting one deserves a second thought.
Connection credentials (an IMAP password, a CRM token, a model provider key) behave the same way: encrypted, never returned, empty field on edit means “leave it”.
Secrets do not reach logs or error text. Node input/output snapshots replace credential
fields with the connection’s name, and every error string goes through a sanitizer that
strips this run’s secret values, Bearer …, sk-…-style keys and passwords inside URLs. The
reason: a chatty remote often quotes the key it was given back inside its own error message,
and without the scrubbing that message would become a viewer for the key.
What leaves the platform
Every outbound HTTP request — from an HTTP node, a connection, a model call — goes through one guarded client with an address policy. The policy is applied on every connection and every redirect, not once against the URL string: an address that points into a private network after a redirect is refused there. Loopback, RFC1918 and link-local ranges are closed, and each request has a hard timeout and a response-size ceiling.
User JavaScript (the JavaScript Code node) runs outside the platform process, in a separate container: no database, no secrets, no file storage, a read-only filesystem, restricted networking, and quotas on time and concurrency. Details are in Your own code.
Channel keys are the right to spend your credits
The public chat link, the widget token and the webhook key are not “API access”. Each grants exactly one thing: running one published workflow, with the credits billed to the workspace owner’s balance. Hence the practice: the chat link is handed to customers, the webhook key is not — the first is protected from abuse by channel rate limits, the second admits a machine.
| Key | What it grants | How it is issued | How to invalidate it |
|---|---|---|---|
| Public chat and widget link | talking to one workflow | automatically on first publish | turn the channel off and republish |
| Webhook key | starting a workflow over HTTP | automatically when publishing to webhook | turn the channel off and republish |
| Widget signing secret | signing end-user JWTs | a button in settings | refresh button |
| Assistant MCP key | driving the platform over MCP | a button in settings | rotate or disable |
Every door, and what is missing from among them, is covered in API access.
Files and signed links
An attachment a workflow returned into a chat is reachable through a signed link: it is unguessable, but it works without a login and without an expiry — otherwise an attachment in a conversation would stop opening a month later. The practical conclusion: such a link is access to the file, and it deserves the same care as the file itself. Files are served with headers that stop the browser executing their contents: uploaded HTML will not become a page on your domain.
How long things live
- Run history is pruned by plan: 7 days on free, 90 on paid. The prune is “soft” — logs and per-node rows are deleted and the heavy inputs/outputs are nulled, while the run row itself keeps its status and timing, so statistics stay intact. Opening an old run says plainly that its details were purged.
- Chat history is never deleted automatically. A person clears it, from the chat’s own controls (editor role). Keep that in mind if a customer contract forbids storing conversations.
- Recorded Telegram group history is off by default, is switched on per workflow, and has its own plan-driven retention and message cap.
- Files, collections, knowledge bases and memory have no expiry — they live until deleted and count against the owner’s storage quotas (Plan limits).
Archiving a workspace deletes none of this: the data stays, only a slot in the workspace quota is freed.
Signing in
The password is stored as a hash; a sign-in issues a token valid for 24 hours, after which a new sign-in is needed. Sign-in and registration attempts are rate-limited. Logins, role changes and secret edits go into a security audit log with time, actor and IP — a log available today only to the installation’s global administrator.
What the platform does not have
An honest list, so you neither hunt for these buttons nor plan around them.
- There is no two-factor authentication.
- There is no separate document on jurisdiction, personal-data processing or retention commitments. What can be said from how it is built: the data sits wherever the installation is deployed, and it leaves only to the providers you connected yourself — the model provider and your integrations’ services. If your data-residency requirements are strict, today’s only answer is to run the platform yourself (Self-hosting).
- There is no one-button export of “all my data”. Exporting is piecemeal: workflows from the editor, files from storage, collections and knowledge bases from their own sections.
- There is no activity log for a workspace admin — only for the installation’s global administrator.