Trust
Security and data handling
Last updated 2 November 2026 · Early-access version · Applies to aibotoffice.ai
This page is for the person answering a vendor questionnaire about Bot Office. It says what the service stores, what it never stores, how keys and credentials are protected, how bots are kept from doing damage, and how to report a problem. It describes the code as it runs today; where something is planned and not built, it says so. The privacy policy has the legal side (controller and processor, your rights).
1. In short
- Bots send status events (which bot, what happened, a status, short labels), not content. Prompts, model outputs and conversations are never part of an event.
- Every key is stored as a SHA-256 hash. The office access code is shown once and cannot be recovered by us.
- Credentials for the tools you connect are encrypted with AES-256-GCM and never returned by the API.
- Bots act only inside the powers you give them. High-impact actions wait for a named person; destructive ones need two.
- One call deletes an office and everything in it; another exports it as JSON.
- There is no third-party certification yet. Everything below is our own description of our own code.
2. Stored and not stored
| Data | Kept? | Detail |
|---|---|---|
| Office name, website address, kit and brand colors | Stored | To name and theme the office |
| Bot ids, display names, roles and platforms | Stored | Bot id at most 64 characters |
| Events: event name, status, run and correlation ids, counts, minutes saved, cost, timestamps | Stored | Only the fields in the event schema; anything else in the request is dropped during validation. Metadata keys outside an allow-list (platform, model, cost_usd, tokens, tags, kind) are dropped |
| Event task title and message | Stored, scrubbed | At most 80 and 140 characters, with personal data replaced (section 3) |
| Tasks on the work queue | Stored as written | Title at most 80 characters, details 1,000, outcome 500. Not scrubbed: write labels, not records |
| Messages between people and bots | Stored as written | At most 500 characters; the last 50 per bot are kept, read or unread, and the oldest is dropped |
| Office memory notes | Stored as written | At most 2,000 characters and 100 notes per office. Text that looks like a key, token or password is refused, not stored |
| Routines (a task template and its schedule) | Stored as written | At most 30 per office; the task they make follows the task limits |
| Webhook endpoints: URL, event types, format (JSON, Slack or Teams), last delivery status | Stored | At most 5 per office, https and public hosts only; answers hide the URL's query. The signing secret is stored encrypted (below) |
| Decision links in approval webhooks | Stored as hashes | Only the SHA-256 of the link, bound to one action and its parameters; expires within 24 hours, single use, and deciding still needs the approver key or office access code |
| Office access codes, view keys, bot links and approver keys | Stored as hashes | SHA-256 only (section 4) |
| Credentials for tools you connect, webhook signing secrets | Stored encrypted | AES-256-GCM (section 5); never returned |
| Action records: which bot asked, the action and its parameters, the reason, tier, decision, approvers' names and notes, result | Stored | Parameters at most 16 KB in all, unknown parameters refused, anything shaped like a password or key removed from text parameters; reason and notes at most 240 characters, scrubbed |
| Rate-limit counters | Stored as keyed hashes | Of the credential or the IP address, never the address itself |
| Prompts, model outputs, chat transcripts, call recordings, email bodies | Not stored | They are not part of any request the office accepts |
| Request bodies beyond the schema and caps | Not stored | Unknown fields are discarded; a request over 16 KB is refused outright; longer text is cut to its limit and the sender is warned |
| Credentials in memory notes | Not stored | Refused with an error that says why |
| Keys in clear | Not stored | Except view keys of offices created before hashing, until their first rotation |
| Decrypted connection credentials | Not stored | They exist only in memory during one call to your tool |
| Data a read action returns from your tool | Not stored | It goes back to the bot that asked and nowhere else |
| Cookies, analytics, tracking pixels | Not used | The site sets no cookies and runs no third-party scripts |
3. Personal data in text
Before an event's task title or message is stored, anything that looks like an email address, a phone number, a US social security number or a payment card number (13–19 digits that pass the card checksum and are not part of an id) is replaced with a placeholder. In ids (run, correlation and bot ids) the same matches become redacted- plus a keyed hash, so related events still group together but the original cannot be read back without our server secret. Other long numbers, such as bank account numbers, are not detected. The same scrub runs on action reasons, approver notes, results and error text. Tasks, messages and memory notes are stored as written, so keep customer records in your own tools and send labels.
4. Keys and access
| Key | What it does | How it is kept and sent |
|---|---|---|
Office access code (bo_live_…) | The owner's key: settings, bots, connections, approvals, export, delete | Shown once when the office is made or the code is rotated; we keep only its hash and cannot show it again. Sent only in the Authorization header, never accepted in an address. Refused on bot links and for bot actions |
| View key (share link) | Watch the office, read only | Hashed. Pages carry it after # in the link, which browsers do not send to servers, and send it to the API in the X-Bo-View-Key header. An old ?k= link still works; the page moves the key into the # part at once |
Bot link (bi_…) | One bot reports and acts as itself, nothing else | Hashed. Sent as a header where the bot's platform allows. Platforms that cannot set headers use the documented path form (/v1/in/<token>/…, /mcp/<token>); that is the one place a key travels in an address, and it shows up in hosting request logs, so prefer the header form. Revocable one by one |
Approver key (ap_…) | One named person approves or rejects actions | Hashed, shown once, sent only in the Authorization header. Revocable at once |
- Rotation. The owner can rotate the access code and view key (
POST /v1/workspaces/:id/keys/rotate, at most 10 times an hour). Rotation retires every access code the office's key index lists, not only the one presented, and old share links stop working. An office created before the key index existed (1 November 2026) retires only the presented code on its first rotation. - No keys in answers. Exports, office views and bot answers never contain a key, a key hash or an encrypted credential; links handed to bots name the office without its view key.
- On your device. The pages keep keys in your browser's local storage when you tick "Remember". Anyone with your browser profile can read them; use "Forget on this device" on a shared computer.
- No accounts yet. There is no sign-in, SSO or multi-factor step today: the access code is the owner's master key, so store it in a password manager.
5. Connection secrets
- Credentials for the tools you connect (ServiceNow, Jira, AWS and the rest), n8n or Make API keys and webhook signing secrets are encrypted at rest with AES-256-GCM under one site-wide secret held as a hosting environment variable, with the key derived by HKDF.
- Each ciphertext is bound to its own record, so a value copied to another record does not decrypt there.
- The site secret can be rotated: the previous secret stays readable for a while, and a daily pass re-encrypts every stored value under the current one.
- The API never returns a credential, and changing a connection's address or identity requires sending its secret again.
- Limit, stated plainly: until a key-management service with per-office keys is in place (planned), anyone with access to both the site secret and the storage could decrypt these values.
6. Actions and approvals
Bots act only through connections the owner added, and only inside the powers each bot is given (by role, with allow and deny patterns). Each action in the catalog has a risk tier:
| Tier | Default gate |
|---|---|
| 0 Read | Runs within the bot's powers |
| 1 Low, reversible | Runs within the bot's powers and limits |
| 2 Reversible change | Runs automatically only when the owner allows it for that bot (the highest automatic tier is 2), else waits for approval |
| 3 High impact (texts, calls, refunds, invoices, external Slack posts, stopping a server) | Waits for a named human approver, who sees the full request |
| 4 Destructive or irreversible | Two distinct approvers (the two-person rule, on by default) and the action's name typed out to confirm |
- Limits per bot (defaults, changeable by the owner): 30 actions an hour and 200 a day, at most 5 targets per action (the blast-radius cap), $50 per action and $500 a day before money moves need approval, and two approvers above $1,000.
- Dry runs. Most catalog actions can preview what they would change without changing it; tier 3 and above preview first where the tool supports it. After a change, a verification read checks the result where possible.
- Kill switch. One setting stops every action in the office: new requests are refused, pending and approved ones are cancelled, and the executor re-checks before each call. A single bot can be benched the same way.
- Approvals are POST requests only, record who decided from the credential (not from a typed name), refuse a second approval by the same person, expire after 24 hours by default, and must match the exact parameters the approver saw.
- Audit trail. Every action record keeps an append-only history (who asked, who approved, what ran, the result). Owners can tighten a tier; tier 3 and 4 actions can never be lowered.
7. Webhooks
Outbound webhooks (up to 5 per office, https only, public hosts only) are signed. Each delivery carries X-BotOffice-Timestamp (unix seconds) and X-BotOffice-Signature: sha256=<HMAC-SHA256 of "timestamp.body" under the hook's secret>. Receivers should check the signature in constant time and refuse timestamps more than five minutes old. The secret is shown once and stored encrypted; an address that carries a user name or password is refused. Deliveries time out after 5 seconds, are retried once on a network error or a server error, and a hook that fails 20 times in a row is switched off.
8. Headers and the browser
- Every page is sent with a Content Security Policy whose
script-srcis'self'only (no inline scripts, no eval),object-src 'none',frame-ancestors 'self',base-uri 'self'andform-action 'self'. Styles still allow'unsafe-inline'because the development server needs it. - Also on every page:
X-Frame-Options: SAMEORIGIN,X-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-originand aPermissions-Policythat turns off camera, microphone and location. - API answers carry
Cache-Control: no-store. - All traffic is served over HTTPS. HSTS is sent by our host on its managed-HTTPS domains; we do not set our own header.
- Text that bots send is shown as text, never as markup.
9. Rate limits and size caps
| What | Limit |
|---|---|
| Events per credential (one bot link or the access code) | 600 a minute |
| Events per office, all credentials together | 1,800 a minute |
| Action requests per bot, over HTTP and MCP together | 60 a minute |
| New offices per client | 10 an hour and 30 a day, plus a site-wide hourly ceiling |
| Brand previews per client | 30 an hour |
| Key rotations per office | 10 an hour |
| Request size | 16 KB; known platform messages up to 1 MB, cut down to ids and status words before anything is kept |
Wrong keys on the office view are counted per client, so guessing slows down. A refused request says why, and a rate-limited one says when to retry (Retry-After).
10. Isolation and outbound requests
- Every key resolves inside its own office only. A key for one office cannot read or write another, and a bot link acts only as its own bot.
- When the service calls out (brand previews, your connected tools, pull connectors, webhooks), it resolves the address and refuses private and internal ones, follows no redirect to them, times out and caps the size it reads. Connected tools must use https on port 443, 8443 or 9443.
- Our internal audit of 29 October 2026 ran 302 scripted and browser checks (cross-office access, server-side request forgery, stored scripts, oversized bodies, rate limits, headers, export and delete); all passed. It was done by us, not by an independent firm.
11. Retention, export and deletion
| Data | Kept for |
|---|---|
| Events | Until the office is deleted. A daily job that deletes events older than 90 days is built but not switched on yet; the privacy policy will say when it is |
| Hourly activity counts | 7 days |
| Read messages | 14 days |
| Brand previews not saved to an office | 24 hours |
| Action records and their history | Until the office is deleted, as an audit trail |
| Everything else (office, bots, keys, connections, tasks, notes, settings) | Until removed or the office is deleted |
- Delete. The owner deletes an office with the access code (
DELETE /v1/workspaces/:id, with the office id typed as confirmation) or by email. It removes the office, its keys, bot links, approvers, events, bots, roles, tasks, routines, notes, messages, connections with their credentials, pull connectors, webhooks, decision links, action records and settings. It cannot remove what your bots already wrote into your own tools. - Export.
GET /v1/workspaces/:id/exportreturns the office's data as JSON, in pages of 500 records, without keys or encrypted credentials. - Backups. There are no separate backups today, so a deleted office cannot be restored.
12. Sub-processors
| Provider | Purpose | Location |
|---|---|---|
| Netlify, Inc. | Hosting, serverless functions, and storage (Netlify Blobs) of all office data | United States |
| Google Fonts | Font files for the website | Global CDN |
The tools you connect receive the requests your bots' actions make; they are your providers, not ours. The full list and its change rule are in the privacy policy.
13. Certification and known limits
No third-party certification yet. Bot Office has no independent audit report or certification today, and this page does not claim one. What we can say is what the code does, as above. Known limits, so you can weigh them:
- No owner accounts, single sign-on or multi-factor step; the access code is a bearer key.
- Bot links in the path form appear in hosting request logs.
- One site-wide secret encrypts credentials (no per-office key-management service yet), and the pseudonym key for scrubbed ids is site-wide too.
- Automatic deletion of old events is not switched on; events stay until the office is deleted.
- Data is processed in the United States; an EU hosting option is planned, not available.
14. Report a vulnerability
Email security@aibotoffice.ai with what you found and how to reproduce it. We answer within two business days and will not pursue good-faith researchers. Please do not test against offices that are not yours; make your own office for free on Build my office. For privacy requests write to privacy@aibotoffice.ai.
See the honesty standard for how we label what is real and what is planned.