Skip to content

Your workspace

A workspace is one Vroxy account: one widget, one knowledge base, one set of conversations, and the people who work them. Everything the widget produces — visitors, chats, feedback, reported errors — belongs to exactly one workspace and is never visible from another.

You can own up to 25 workspaces. Create another one from the workspace switcher in the sidebar (“+ New workspace”); you become its owner and land on its Embed page with a fresh API token.

Every workspace page lives under a tenant-scoped path:

/w/<workspace-id>/<slug>/chats

<workspace-id> is the stable lookup key — it never changes. <slug> is the human-readable part and is purely cosmetic: a stale slug still resolves and redirects (301) to the canonical URL. Because the id is in the URL, a link you paste into Slack always opens the workspace you were looking at, not “whichever workspace the recipient last used”.

Bare /workspace (and any older /workspace/… bookmark) redirects to the canonical URL for your current workspace.

Dashboard — chats today and total, open feedback, visitors active in the last 24 hours, and the dispatch connection status (see Feedback to fix).

Chats — every conversation the widget has produced. Covered below.

Rooms — internal, member-to-member chat that visitors never see. See Rooms.

Feedback — UI feedback filed from the widget by your own admins. Each ticket moves through opentriagedresolved, or is dismissed. See Feedback to fix.

Visitors — everyone the widget has seen. Filter to those seen in the last 24 hours, or split identified (has an email or an external_id) from anonymous. A visitor’s page shows their identity fields, whatever custom attributes you passed to identify, their ten most recent chats and their most recent feedback. Deleting a visitor is a soft delete — their chats and feedback are hidden, not purged — and can be undone with Restore.

Docs — the knowledge base the bot answers from. See Knowledge base.

Tools — custom actions you teach the bot. See Custom bot tools.

Errors — exceptions reported from your app and from the widget. See Error reporting.

Embed — installation only: the snippet, your public key, the identity-verification secret, the origin allowlist, and the “regenerate API key” button.

Settings — how the widget looks and talks: header title, greeting, brand color, bot model, system prompt, glossary, visitor tracking, chat auto-close. See Bot settings.

API tokens — server-to-server keys owned by this workspace.

Members — who is in the workspace and at what level.

The chat list is paginated 25 at a time. You can filter by state (live vs ended) and by Wants a person — chats where the visitor, or the bot on their behalf, asked for a human and the chat is still open. That second filter is the queue you actually work.

Search (?q=) is a loose, case-insensitive substring match across three places you might remember a conversation from: the chat’s title, the visitor’s identified name or email, and the body of every message in it. When the hit is inside a transcript, the list shows a highlighted snippet of the matching message so you don’t have to open every result.

Opening a chat gives you the full transcript — visitor messages, bot replies, attachments, and the page the visitor was on when they started (and where they are now). From there you can:

  • Reply. Replying takes over the conversation: the chat flips to human handling and the bot stands down, so the visitor never hears two voices in one thread. Your reply is labelled as coming from you, not the bot. A reply is at most 4,000 characters.
  • Hand back to bot. Re-arms the bot for the next message.
  • Close. Ends the conversation. Once a chat is closed nobody can reply to it — the visitor starts a new conversation instead, and it arrives as a new chat.
  • Attach files. Images and documents, up to five per reply. Files upload the moment you attach them, with per-file progress.
  • Request a screenshot. Sends a request to the visitor’s widget. They see a consent prompt; nothing is captured unless they hit Share. The capture arrives as a normal attachment on their next message. Only works while the chat is open.

Access to a workspace comes from a membership, not from ownership. Each membership sits at one of four levels:

Level What it’s for
operator Someone who answers chats, and nothing else.
member Day-to-day work: chats, docs, feedback, tools, errors, settings (read).
admin Everything except owning the workspace.
owner Full control. Every workspace has exactly one.

Under the hood a level is a bundle of named capabilities. These are the capabilities that exist:

Capability What it allows
chats.read See conversations and transcripts.
chats.reply Reply as a human operator, hand back to the bot, close a chat.
feedback.read See UI feedback tickets.
feedback.manage Triage, resolve, and dismiss feedback.
visitors.read See the visitor list and their details.
visitors.delete Delete visitor records.
docs.read See the knowledge base.
docs.write Create, edit, publish, scrape, and delete knowledge-base docs.
tools.read See the workspace’s custom bot tools.
tools.write Create and edit custom bot tools, including ones that make server-side requests.
errors.read See errors reported from your app and the widget.
rooms.read See the workspace’s chat rooms and their messages.
rooms.write Create rooms, join them, and post messages and attachments.
rooms.manage Edit or delete any room and remove any member’s message.
settings.read See branding and bot settings.
settings.write Change branding, the bot’s system prompt, and the model it uses.
embed.read See the embed snippet and public key.
embed.manage Rotate API keys and change the origin allowlist.
api_tokens.read See the workspace’s API tokens.
api_tokens.manage Create and revoke API tokens.
members.read See who is in the workspace.
members.manage Invite people, change their level, and remove them.
workspace.manage Reserved to the owner — the one capability an admin never holds.

And this is how the levels map onto them:

  • operatorchats.read, chats.reply, feedback.read, visitors.read, members.read, rooms.read, rooms.write.
  • member — everything an operator has, plus feedback.manage, docs.read, docs.write, tools.read, errors.read, settings.read, embed.read, api_tokens.read.
  • admin — every capability except workspace.manage. That includes settings.write, embed.manage, api_tokens.manage, tools.write, members.manage, visitors.delete and rooms.manage.
  • owner — every capability, including any added later.

Two rules follow from the way capabilities are defined, and they’re worth knowing:

  • A write implies its read. Holding docs.write always also grants docs.read. You never end up able to edit something you can’t open.
  • A level is a floor, not a ceiling. Individual capabilities can be granted to one person in one workspace on top of their level — that’s how “an operator who can also edit the knowledge base” works without inventing a new level.

Managing members asks two separate questions, and passing the first doesn’t mean passing the second:

  1. May you manage members at all? (members.manage)
  2. May you manage this member?

The second is a rank rule. You may only act on someone strictly below your own level, and you may never grant a level above your own. So an admin can promote a member to admin’s level but not to owner, and can’t demote or remove another admin. The owner is the exception: they run the place and can act on anyone.

The owner’s seat is immovable: it can’t be removed or demoted from the Members page by anyone, including the owner. A workspace always has exactly one.

Removing yourself is different: leaving needs no member-management capability, because nobody needs permission to walk out. Anyone except the owner can remove their own seat from the Members page, and you’re returned to whichever workspace you still have access to.

The “who’s around” signal is derived from real activity — your membership’s last-active timestamp is touched as you use the workspace, and anyone who can reply to chats and has been seen in the last five minutes counts as available. There’s no manual “I’m available” toggle, because nobody remembers to switch one off and a stale “online” promises your visitor a person who isn’t there.

Invitations are addressed to an email address, not to an account — most invitees don’t have one yet. Invite from the Members page, pick the level (you can’t offer a level above your own), and they get a link.

A few things to know:

  • A mismatched account is refused. Accepting an invitation checks that the signed-in account’s email matches the address that was invited. Otherwise forwarding the email would hand your workspace to whoever received it.
  • Invitations expire after 14 days and a workspace can hold at most 50 pending at once.
  • “Resend” issues a new link and retires the old one. Only a one-way digest of the token is stored, so the original link can’t be recovered or re-sent — a resend is a fresh invitation to the same address at the same level.
  • Revoking is permanent. A revoked invitation can’t be restored; issue a new one. Revoking an invitation follows the same rank rule as issuing one.
  • Re-inviting an existing member never demotes them. If someone is already in the workspace at a higher level than the invitation says, they keep the higher level.
  • Losing your seat retires the invitations you issued. If you’re removed from a workspace, every invitation still pending in your name is revoked with you.

You can’t invite an address that’s already a member, and you can’t have two pending invitations to the same address in the same workspace.