Permissions & scopes

Scopes a key can carry.

A key carries a set of scopes. Each endpoint requires a specific scope; a call without it returns 403 forbidden with the missing scope named.

ScopeFriendly nameEndpoints it unlocks
ai_explainInterpret & explaininterpret, conversations, messages, embed tokens
ai_generatePropose codegenerate (proposes code; never persists)
analysis_tabAnalysesread an analysis, and ask for a fresh run
code_readRead coderead project source (/source)
code_writeEdit & save projectsave a new version (/versions)
export_plcExport to PLC formatstart & download a PLC export
export_pdfExport to PDFstart & download a PDF report
hmi_viewView HMIread live values & history; carried by read-only embed tokens
hmi_editRequest live tagsask the DCA to read specific tags on demand (/hmi/request-tags)

project_upload exists as an organization permission but unlocks nothing here: there is no create-a-project verb on the API, so a key never needs it.

Reading the project list (GET /projects) and one project's metadata (GET /projects/{id}) needs no extra scope — any valid key may discover the projects in its scope.

Generate and save are separate scopes on purpose. ai_generate only drafts a reviewable proposal; persisting it requires code_write. A generate-only key can never deploy a machine-bound version.

Project scope

A key may optionally be restricted to specific projects. When set, any project-targeted call to a project outside the scope returns 403 project_scope_forbidden.

A project-scoped key may add a version to an in-scope project, but no key can create a new project identity — a machine is onboarded in the app or through a version-source connector, never by an API caller.