Permissions
A key carries an explicit list of permissions, and nothing is granted by default. A request with a valid key but the wrong permission is rejected with 403, distinct from the 401 you get for a missing or invalid key.
Workflow permissions can be granted on all workflows or on individual workflows, so a key handed to one integration can be limited to the one workflow it needs. Library permissions always cover the whole project library.
| Permission | Name | Allows |
|---|---|---|
workflows.run | Run | Start the workflow, synchronously or through the queue, and expose it over MCP. |
workflows.read | Read | List the workflow and poll the status of its runs. |
library.read | Browse | List directories and files, and download file contents. |
library.write | Upload | Create files and complete uploads. |
library.delete | Delete | Permanently remove files from the library. |
databases.read | Read | List databases and tables, and read a table's schema and rows. |
databases.write | Write | Insert rows, update cells, and start CSV imports. |
databases.delete | Delete rows | Permanently delete rows. Does not allow dropping tables or columns. |
databases.schema | Change schema | Create and delete tables and columns. Deleting either destroys the data it held, so grant this only where structure genuinely changes. |
databases.query | Run SQL | Run arbitrary SQL. A SELECT and a DROP cannot be told apart without parsing the statement, so this grant is as powerful as the worst query it could carry — treat it as full control of the database. |
databases.admin | Provision | Create and destroy whole databases. A new database is real, billable infrastructure from the moment it exists. |
Listing reflects your permissions
Listing workflows returns only the workflows your key can read. A key scoped to a single workflow sees exactly that one, so the endpoint never reveals the rest of the project.