{
  "openapi": "3.1.0",
  "info": {
    "version": "0.27.5",
    "title": "Management API",
    "description": "Vilna Management API. Manage workspaces, projects, team members, and API keys.\n\n**Authentication**\n\nEvery request must include a management key (`vilna_mgt_...`) in the `X-Api-Key` header. Management keys are workspace-scoped: each key only sees the workspace it was created in. Every operation lists the permission scopes its key must hold (e.g., `mgt:project:write`). A key missing the required scope gets `403 Forbidden`.\n\n**Key Types**\n\nVilna has three key types, each with its own prefix. Don't mix them:\n\n- `vilna_mgt_...`: management keys authenticate calls to this API (manage workspaces, projects, members, and other keys).\n- `vilna_api_...`: project-scoped API keys for the public Vilna API (`api.vilna.io`).\n- `vilna_rpc_...`: workspace-scoped keys for blockchain JSON-RPC endpoints (`rpc.vilna.io`).\n\nThis API creates and revokes API keys and RPC keys. Management keys are issued via the Vilna dashboard and can't be listed or rotated here. Their lifecycle events (`mgt_key.created`, `mgt_key.revoked`) still appear in the activity log so admins can audit changes.\n\n**Quick Links**\n\n- [Authorization Guide](/apis/mgmt/authorization) - Roles, permissions, and access control\n- [Quick Start Guide](/guides/quickstart) - Step-by-step integration tutorial\n\n**Endpoints**\n\nWorkspace Management\n\n- **[Members](#tag/member)** - Workspace members and their roles\n- **[Invitations](#tag/invitation)** - Workspace invitation lifecycle\n- **[Projects](#tag/project)** - Create, update, and delete projects within a workspace\n- **[Project Members](#tag/project_member)** - Assign and manage project-level member access\n- **[Activity Log](#tag/log)** - Audit trail of workspace activity\n\nKey Management\n\n- **[API Keys](#tag/api_key)** - Project-scoped API keys for the public Vilna API\n- **[RPC Keys](#tag/rpc_key)** - Workspace-scoped keys for blockchain RPC endpoints\n\nRPC Access\n\n- **[RPC](#tag/rpc)** - Workspace RPC endpoint details\n\nInfrastructure\n\n- **[Version](#tag/version)** - Service version info\n\n**Array Query Parameters**\n\nFilters that accept multiple values (`status`, `role`, `type`, etc.) use repeated keys:\n\n- ✅ `?status=active&status=revoked`\n- ❌ `?status=active,revoked`\n\nThis follows the OpenAPI default (`style: form, explode: true`).\n\n**Need Help?**\n\nVisit our [documentation portal](/apis/mgmt/authorization) for detailed guides and examples.\n",
    "contact": {
      "email": "support@vilna.io",
      "name": "Vilna API Team",
      "url": "https://vilna.io"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0.html"
    },
    "termsOfService": "https://docs.vilna.io/legal/terms"
  },
  "servers": [
    {
      "url": "https://mgmt.vilna.io/v1",
      "description": "Vilna Management API."
    }
  ],
  "security": [
    {
      "Auth": []
    }
  ],
  "tags": [
    {
      "name": "member",
      "x-displayName": "Members",
      "description": "Workspace members and their roles (`admin`, `member`).",
      "x-keywords": {
        "includes": [
          "team members",
          "workspace members",
          "roles",
          "permissions",
          "RBAC"
        ]
      }
    },
    {
      "name": "invitation",
      "x-displayName": "Invitations",
      "description": "Workspace invitation lifecycle (`pending`, `accepted`, `declined`, `revoked`, `expired`).",
      "x-keywords": {
        "includes": [
          "invite member",
          "team invitation",
          "revoke invitation"
        ]
      }
    },
    {
      "name": "log",
      "x-displayName": "Activity Log",
      "description": "Audit trail of member, project, and key activity within a workspace.",
      "x-keywords": {
        "includes": [
          "audit log",
          "activity feed",
          "events"
        ]
      }
    },
    {
      "name": "project",
      "x-displayName": "Projects",
      "description": "Create, update, and delete projects within a workspace.",
      "x-keywords": {
        "includes": [
          "create project",
          "delete project",
          "list projects",
          "project settings"
        ]
      }
    },
    {
      "name": "project_member",
      "x-displayName": "Project Members",
      "description": "Project-level grants for workspace members (`editor`, `viewer`).",
      "x-keywords": {
        "includes": [
          "project access",
          "assign role",
          "editor",
          "viewer",
          "project permissions"
        ]
      }
    },
    {
      "name": "rpc",
      "x-displayName": "RPC",
      "description": "Workspace-scoped access to blockchain JSON-RPC nodes.",
      "x-keywords": {
        "includes": [
          "rpc",
          "blockchain rpc",
          "json-rpc"
        ]
      }
    },
    {
      "name": "api_key",
      "x-displayName": "API Keys",
      "description": "Manage project-scoped API keys (`vilna_api_...`) used to authenticate the public Vilna API (`api.vilna.io`). A project must exist before a key can be created. The raw secret is returned only in the create response.\n",
      "x-keywords": {
        "includes": [
          "create API key",
          "revoke API key",
          "API key permissions",
          "API authentication",
          "API credentials"
        ]
      }
    },
    {
      "name": "rpc_key",
      "x-displayName": "RPC Keys",
      "description": "Manage workspace-scoped RPC keys (`vilna_rpc_...`) used to authenticate the blockchain JSON-RPC gateway (`rpc.vilna.io`). The raw secret is returned only in the create response.\n",
      "x-keywords": {
        "includes": [
          "RPC key",
          "blockchain node access",
          "blockchain RPC",
          "JSON-RPC"
        ]
      }
    },
    {
      "name": "version",
      "x-displayName": "Version",
      "description": "Service version information."
    }
  ],
  "paths": {
    "/workspaces/{workspace_id}/members": {
      "get": {
        "summary": "List workspace members",
        "description": "Return workspace members with their roles.",
        "operationId": "list-workspace-members",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortWorkspaceMembers"
          },
          {
            "$ref": "#/components/parameters/workspaceMembersFilterRole"
          },
          {
            "$ref": "#/components/parameters/workspaceMembersFilterSearch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/workspace_members_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "member"
        ]
      }
    },
    "/workspaces/{workspace_id}/members/{user_id}": {
      "patch": {
        "summary": "Update workspace member",
        "description": "Update a member's workspace role.",
        "operationId": "patch-workspace-member",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/userID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/update_workspace_member_request"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/workspace_member_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "422": {
            "$ref": "#/components/responses/precondition_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "member"
        ]
      },
      "delete": {
        "summary": "Remove workspace member",
        "description": "Remove a member from the workspace and revoke all of their project grants.",
        "operationId": "remove-workspace-member",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:delete"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/userID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "member"
        ]
      }
    },
    "/workspaces/{workspace_id}/invitations": {
      "get": {
        "summary": "List workspace invitations",
        "description": "Return workspace invitations in any lifecycle status.",
        "operationId": "list-workspace-invitations",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortInvitations"
          },
          {
            "$ref": "#/components/parameters/invitationsFilterStatus"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/invitations_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "invitation"
        ]
      },
      "post": {
        "summary": "Create workspace invitation",
        "description": "Create an invitation by email with an optional bundle of project grants. Idempotent: returns `200 OK` if a pending invitation for the same recipient already exists.\n",
        "operationId": "create-workspace-invitation",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/create_invitation_request"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/invitation_response"
          },
          "201": {
            "$ref": "#/components/responses/invitation_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "422": {
            "$ref": "#/components/responses/precondition_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "invitation"
        ]
      }
    },
    "/workspaces/{workspace_id}/invitations/{invitation_id}/actions/revoke": {
      "post": {
        "summary": "Revoke workspace invitation",
        "description": "Revoke a pending invitation. Invitations in terminal status cannot be revoked.",
        "operationId": "revoke-workspace-invitation",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/invitationID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "invitation"
        ]
      }
    },
    "/workspaces/{workspace_id}/rpc": {
      "get": {
        "summary": "Get workspace RPC",
        "description": "Return the workspace RPC singleton configuration. Provisioned automatically with every workspace and always available to its members.\n",
        "operationId": "get-workspace-rpc",
        "security": [
          {
            "Auth": [
              "mgt:workspace:self:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/rpc_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "rpc"
        ]
      }
    },
    "/workspaces/{workspace_id}/rpc/keys": {
      "get": {
        "summary": "List RPC keys",
        "description": "Return workspace RPC keys.",
        "operationId": "list-workspace-rpc-keys",
        "security": [
          {
            "Auth": [
              "mgt:workspace:rpc_key:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortAuthKeys"
          },
          {
            "$ref": "#/components/parameters/rpcKeysFilterStatus"
          },
          {
            "$ref": "#/components/parameters/rpcKeysFilterSearch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/rpc_keys_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "rpc_key"
        ]
      },
      "post": {
        "summary": "Create RPC key",
        "description": "Create a new workspace RPC key. The raw secret is returned once and cannot be retrieved again.",
        "operationId": "create-workspace-rpc-key",
        "security": [
          {
            "Auth": [
              "mgt:workspace:rpc_key:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/create_rpc_key_request"
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/rpc_key_created_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "422": {
            "$ref": "#/components/responses/precondition_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "rpc_key"
        ]
      }
    },
    "/workspaces/{workspace_id}/rpc/keys/{key_id}": {
      "get": {
        "summary": "Get RPC key",
        "description": "Return a workspace RPC key by ID.",
        "operationId": "get-workspace-rpc-key",
        "security": [
          {
            "Auth": [
              "mgt:workspace:rpc_key:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/keyID"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/rpc_key_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "rpc_key"
        ]
      }
    },
    "/workspaces/{workspace_id}/rpc/keys/{key_id}/actions/revoke": {
      "post": {
        "summary": "Revoke RPC key",
        "description": "Revoke a workspace RPC key. Once revoked, the key can no longer be used for authentication.",
        "operationId": "revoke-workspace-rpc-key",
        "security": [
          {
            "Auth": [
              "mgt:workspace:rpc_key:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/keyID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "rpc_key"
        ]
      }
    },
    "/workspaces/{workspace_id}/logs": {
      "get": {
        "summary": "List activity log",
        "description": "Return workspace activity events in reverse-chronological order.",
        "operationId": "list-workspace-logs",
        "security": [
          {
            "Auth": [
              "mgt:workspace:self:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortLogs"
          },
          {
            "$ref": "#/components/parameters/logsFilterType"
          },
          {
            "$ref": "#/components/parameters/logsFilterActorID"
          },
          {
            "$ref": "#/components/parameters/logsFilterFrom"
          },
          {
            "$ref": "#/components/parameters/logsFilterTo"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/log_events_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "log"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects": {
      "get": {
        "summary": "List workspace projects",
        "description": "Return projects within a workspace. Workspace admins receive all projects; members receive only projects where they hold an explicit grant.\n",
        "operationId": "list-workspace-projects",
        "security": [
          {
            "Auth": [
              "mgt:workspace:project:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortProjects"
          },
          {
            "$ref": "#/components/parameters/projectsFilterStatus"
          },
          {
            "$ref": "#/components/parameters/projectsFilterSearch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/projects_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project"
        ]
      },
      "post": {
        "summary": "Create project",
        "description": "Create a new project in the workspace.",
        "operationId": "create-workspace-project",
        "security": [
          {
            "Auth": [
              "mgt:workspace:project:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/create_project_request"
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/project_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}": {
      "get": {
        "summary": "Get project",
        "description": "Return a project by ID.",
        "operationId": "get-workspace-project",
        "security": [
          {
            "Auth": [
              "mgt:workspace:project:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/project_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project"
        ]
      },
      "patch": {
        "summary": "Update project",
        "description": "Update a project's name.",
        "operationId": "patch-workspace-project",
        "security": [
          {
            "Auth": [
              "mgt:workspace:project:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/update_project_request"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/project_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project"
        ]
      },
      "delete": {
        "summary": "Delete project",
        "description": "Soft-delete a project. Nested keys and member grants are purged asynchronously.",
        "operationId": "delete-workspace-project",
        "security": [
          {
            "Auth": [
              "mgt:project:self:delete"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}/members": {
      "get": {
        "summary": "List project members",
        "description": "Return explicit project grants (editors and viewers). Workspace admins have implicit access and are not listed.",
        "operationId": "list-workspace-project-members",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortProjectMembers"
          },
          {
            "$ref": "#/components/parameters/projectMembersFilterRole"
          },
          {
            "$ref": "#/components/parameters/projectMembersFilterSearch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/project_members_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project_member"
        ]
      },
      "post": {
        "summary": "Assign project member",
        "description": "Grant a workspace member project-level access (`editor` or `viewer`). Idempotent: returns `200 OK` if the grant already exists with the same role, `409 Conflict` if it exists with a different role.\n",
        "operationId": "assign-workspace-project-member",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/create_project_member_request"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/project_member_response"
          },
          "201": {
            "$ref": "#/components/responses/project_member_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "409": {
            "$ref": "#/components/responses/conflict_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project_member"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}/members/{user_id}": {
      "patch": {
        "summary": "Update project member",
        "description": "Update a member's project role.",
        "operationId": "patch-workspace-project-member",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/userID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/update_project_member_request"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/project_member_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project_member"
        ]
      },
      "delete": {
        "summary": "Remove project member",
        "description": "Remove a project grant. The member remains in the workspace.",
        "operationId": "remove-workspace-project-member",
        "security": [
          {
            "Auth": [
              "mgt:workspace:member:delete"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/userID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "project_member"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}/keys": {
      "get": {
        "summary": "List project keys",
        "description": "Return project API keys.",
        "operationId": "list-workspace-project-keys",
        "security": [
          {
            "Auth": [
              "mgt:project:api_key:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/page"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/sortAuthKeys"
          },
          {
            "$ref": "#/components/parameters/apiKeysFilterStatus"
          },
          {
            "$ref": "#/components/parameters/apiKeysFilterSearch"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/api_keys_list_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "api_key"
        ]
      },
      "post": {
        "summary": "Create project key",
        "description": "Create a new project API key. The raw secret is returned once and cannot be retrieved again.",
        "operationId": "create-workspace-project-key",
        "security": [
          {
            "Auth": [
              "mgt:project:api_key:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/create_api_key_request"
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/api_key_created_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "422": {
            "$ref": "#/components/responses/precondition_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "api_key"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}/keys/{key_id}": {
      "get": {
        "summary": "Get project key",
        "description": "Return a project API key by ID.",
        "operationId": "get-workspace-project-key",
        "security": [
          {
            "Auth": [
              "mgt:project:api_key:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/keyID"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/api_key_response"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "api_key"
        ]
      }
    },
    "/workspaces/{workspace_id}/projects/{project_id}/keys/{key_id}/actions/revoke": {
      "post": {
        "summary": "Revoke project key",
        "description": "Revoke a project API key. Once revoked, the key can no longer be used for authentication.",
        "operationId": "revoke-workspace-project-key",
        "security": [
          {
            "Auth": [
              "mgt:project:api_key:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/workspaceID"
          },
          {
            "$ref": "#/components/parameters/projectID"
          },
          {
            "$ref": "#/components/parameters/keyID"
          }
        ],
        "responses": {
          "204": {
            "$ref": "#/components/responses/no_content_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "401": {
            "$ref": "#/components/responses/unauthorized_problem"
          },
          "403": {
            "$ref": "#/components/responses/forbidden_problem"
          },
          "404": {
            "$ref": "#/components/responses/not_found_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "api_key"
        ]
      }
    },
    "/version": {
      "get": {
        "summary": "Get service version",
        "description": "Return the current API version.",
        "operationId": "get-version",
        "security": [],
        "responses": {
          "200": {
            "$ref": "#/components/responses/version_response"
          },
          "400": {
            "$ref": "#/components/responses/invalid_request_problem"
          },
          "default": {
            "$ref": "#/components/responses/problem"
          }
        },
        "tags": [
          "version"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "Auth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Management key (`vilna_mgt_...`). Send it in the `X-Api-Key` header on every request. The key must hold all scopes listed on the operation; a missing scope yields `403 Forbidden`. API keys (`vilna_api_...`) and RPC keys (`vilna_rpc_...`) are not accepted here; they authenticate the public API and RPC gateways respectively.\n"
      }
    },
    "schemas": {
      "UUID": {
        "type": "string",
        "format": "uuid",
        "description": "Unique identifier (UUID v4).",
        "example": "550e8400-e29b-41d4-a716-446655440000"
      },
      "WorkspaceRole": {
        "type": "string",
        "enum": [
          "owner",
          "admin",
          "member"
        ],
        "description": "Role assigned to a user within a workspace.",
        "x-enumDescriptions": {
          "owner": "Workspace creator; full admin rights plus deleting or transferring the workspace. Only one per workspace, and never assignable via invitation or role change.",
          "admin": "Manages members, projects, invitations, and keys; implicit access to every project in the workspace.",
          "member": "Read-only at workspace level; project access requires an explicit grant."
        },
        "example": "admin"
      },
      "ProblemType": {
        "type": "string",
        "format": "uri",
        "description": "A URI that identifies the error type.\nOpen it in a browser to read about this category of error.\n",
        "example": "https://docs.vilna.io/apis/problems/internal-error"
      },
      "ProblemTitle": {
        "type": "string",
        "description": "A short summary of the error type.\nUse `detail` for information specific to this occurrence.\n",
        "example": "Bad Request"
      },
      "ProblemStatus": {
        "type": "integer",
        "description": "The HTTP status code for this error.\nMatches the status code of the HTTP response.\n",
        "example": 400
      },
      "ProblemDetail": {
        "type": "string",
        "description": "A human-readable explanation of what went wrong in this specific case.\nMay be localized.\n",
        "example": "The address is already assigned to another invoice"
      },
      "ProblemInstance": {
        "type": "string",
        "description": "A URI that identifies this specific error occurrence.\nInclude this value when contacting support.\n",
        "example": "/errors?id=XXXXXX-xxxxx"
      },
      "ProblemCode": {
        "type": "string",
        "description": "Stable machine-readable error code (`{domain}.{reason}`) for programmatic error handling. Unlike the HTTP `status` or free-form `detail`, this code is guaranteed not to change between versions for a given error condition, so it is safe to branch on in client code. Defaults to `unspecified` when the server has not assigned a specific code.\n",
        "default": "unspecified",
        "example": "resource.not_found"
      },
      "Problem": {
        "type": "object",
        "description": "Error response following [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt). Served with `Content-Type: application/problem+json`. All error responses use this format; branch on `code` for programmatic handling and surface `detail` to end users.\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus"
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode"
          }
        }
      },
      "Email": {
        "type": "string",
        "format": "email",
        "maxLength": 128,
        "description": "Email address.",
        "example": "user@example.com"
      },
      "User": {
        "type": "object",
        "description": "A workspace participant. Mirrors a Kratos identity.",
        "required": [
          "id",
          "email"
        ],
        "properties": {
          "id": {
            "description": "User UUID.",
            "$ref": "#/components/schemas/UUID"
          },
          "email": {
            "$ref": "#/components/schemas/Email"
          },
          "first_name": {
            "type": "string",
            "description": "Given name from identity traits.",
            "example": "John"
          },
          "last_name": {
            "type": "string",
            "description": "Family name from identity traits.",
            "example": "Doe"
          },
          "avatar": {
            "type": "string",
            "format": "uri",
            "description": "Absolute http(s) URL to the user's profile image.",
            "example": "https://cdn.vilna.io/avatars/0193d4a1.jpg"
          }
        },
        "example": {
          "id": "0193d4a1-8f03-7e30-b4c5-6d7e8f901234",
          "email": "john@example.com",
          "first_name": "John",
          "last_name": "Doe",
          "avatar": "https://cdn.vilna.io/avatars/0193d4a1.jpg"
        }
      },
      "WorkspaceMember": {
        "type": "object",
        "description": "An accepted workspace member.",
        "required": [
          "user",
          "role",
          "joined_at"
        ],
        "properties": {
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "role": {
            "$ref": "#/components/schemas/WorkspaceRole"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the member joined the workspace.",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "example": {
          "user": {
            "id": "0193d4a1-8f03-7e30-b4c5-6d7e8f901234",
            "email": "user@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "avatar": "https://cdn.vilna.io/avatars/0193d4a1.jpg"
          },
          "role": "admin",
          "joined_at": "2024-01-15T10:30:00Z"
        }
      },
      "PaginationMeta": {
        "type": "object",
        "description": "Pagination metadata returned on every list response. `page` and `limit` echo the values used to build this page (defaults are applied when the request omits them). `total` and `total_pages` reflect the full result set after any filters are applied.\n",
        "properties": {
          "limit": {
            "description": "Page size used to build this response.",
            "type": "integer",
            "format": "uint",
            "minimum": 1
          },
          "page": {
            "description": "Index of the page returned, starting at 1.",
            "type": "integer",
            "format": "uint",
            "minimum": 1
          },
          "total": {
            "description": "Total number of items matching the request across all pages.",
            "type": "integer",
            "format": "uint",
            "minimum": 0
          },
          "total_pages": {
            "description": "Total number of pages available at the current `limit`.",
            "type": "integer",
            "format": "uint",
            "minimum": 0
          }
        },
        "required": [
          "total",
          "page",
          "limit",
          "total_pages"
        ],
        "example": {
          "limit": 20,
          "page": 1,
          "total": 42,
          "total_pages": 3
        }
      },
      "InvalidRequestProblem": {
        "type": "object",
        "description": "Problem details for invalid request errors (400 Bad Request).\n\nExtends base Problem with field-specific validation error details\nfollowing [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/invalid-request"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Invalid Request"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 400
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "Validation error"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "blockchain.name_too_long"
          },
          "fields": {
            "type": "array",
            "description": "List of invalid fields in the request",
            "items": {
              "type": "object",
              "required": [
                "name",
                "reason"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The name of the invalid field",
                  "example": "meta"
                },
                "reason": {
                  "type": "string",
                  "description": "Why this field is invalid",
                  "example": "Exceeded maximum data size — must not exceed 1000 characters"
                }
              }
            }
          }
        }
      },
      "UnauthorizedProblem": {
        "type": "object",
        "description": "Standard problem response when authentication is missing or invalid,\nfollowing [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/unauthorized"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Unauthorized"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 401
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "Missing or invalid authentication credentials"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "auth.unauthorized"
          }
        }
      },
      "ForbiddenProblem": {
        "type": "object",
        "description": "Standard problem response when the authenticated user lacks permission\nto access the requested resource, following [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/forbidden"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Forbidden"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 403
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "You do not have permission to perform this action"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "chain.not_allowed"
          }
        }
      },
      "NotFoundProblem": {
        "type": "object",
        "description": "Problem details for not found errors (404 Not Found).\n\nStandard problem response when requested resource does not exist\nfollowing [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/not-found"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Not Found"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 404
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "The requested resource was not found"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "blockchain.not_found"
          }
        }
      },
      "AssignableWorkspaceRole": {
        "type": "string",
        "enum": [
          "admin",
          "member"
        ],
        "description": "Subset of `WorkspaceRole` that can be assigned to a member: `admin` or `member`. `owner` is excluded; it's set when a workspace is created and can't be granted afterwards. Used for invitations and member role changes.",
        "x-enumDescriptions": {
          "admin": "Manages members, projects, invitations, and keys; implicit access to every project in the workspace.",
          "member": "Read-only at workspace level; project access requires an explicit grant."
        },
        "example": "admin"
      },
      "PreconditionProblem": {
        "type": "object",
        "description": "Problem details for precondition failed errors (422 Unprocessable Entity).\n\nStandard problem response when request cannot be processed due to failed\nbusiness rule validation following [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/precondition-failed"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Precondition Failed"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 422
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "The request cannot be processed due to failed business rule validation"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "simulation.failed"
          },
          "fields": {
            "type": "array",
            "description": "List of fields that failed precondition validation",
            "items": {
              "type": "object",
              "required": [
                "name",
                "reason"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The name of the field that failed validation",
                  "example": "status"
                },
                "reason": {
                  "type": "string",
                  "description": "Why the precondition failed for this field",
                  "example": "Cannot transition from archived to active state"
                }
              }
            }
          }
        }
      },
      "InvitationStatus": {
        "type": "string",
        "enum": [
          "pending",
          "accepted",
          "declined",
          "revoked",
          "expired"
        ],
        "description": "Current invitation lifecycle status.",
        "x-enumDescriptions": {
          "pending": "Invitation is awaiting a response.",
          "accepted": "Invitation was accepted and the workspace membership was created.",
          "declined": "Invitation was declined by the invitee.",
          "revoked": "Invitation was cancelled by a workspace admin.",
          "expired": "Invitation was not answered before its expiration time."
        },
        "example": "pending"
      },
      "WorkspaceName": {
        "type": "string",
        "maxLength": 32,
        "description": "Human-readable workspace name.",
        "example": "My Workspace"
      },
      "CreatedAt": {
        "description": "Timestamp when the resource was created. RFC 3339 / ISO 8601, UTC.",
        "format": "date-time",
        "type": "string",
        "example": "2024-01-15T10:30:00Z"
      },
      "WorkspaceSummary": {
        "type": "object",
        "description": "Basic workspace info used when referencing a workspace from another resource.",
        "required": [
          "id",
          "name",
          "created_at"
        ],
        "properties": {
          "id": {
            "description": "Unique workspace identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "name": {
            "$ref": "#/components/schemas/WorkspaceName"
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          }
        },
        "example": {
          "id": "550e8400-e29b-41d4-a716-446655440000",
          "name": "Acme Inc",
          "created_at": "2024-01-15T10:30:00Z"
        }
      },
      "ExpiresAt": {
        "description": "Timestamp when the resource expires. RFC 3339 / ISO 8601, UTC. Absent if the resource never expires.",
        "format": "date-time",
        "type": "string",
        "example": "2025-01-15T10:30:00Z"
      },
      "ProjectName": {
        "type": "string",
        "maxLength": 32,
        "description": "Human-readable project name.",
        "example": "Production"
      },
      "ProjectSummary": {
        "type": "object",
        "description": "Basic project info used when referencing a project from another resource.",
        "required": [
          "id",
          "name",
          "created_at"
        ],
        "properties": {
          "id": {
            "description": "Unique project identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "name": {
            "$ref": "#/components/schemas/ProjectName"
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          }
        },
        "example": {
          "id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
          "name": "Production",
          "created_at": "2024-01-15T10:30:00Z"
        }
      },
      "ProjectRole": {
        "type": "string",
        "enum": [
          "editor",
          "viewer"
        ],
        "description": "Project-level role for a workspace member.",
        "x-enumDescriptions": {
          "editor": "Read and write access to project resources.",
          "viewer": "Read-only access to project resources."
        },
        "example": "editor"
      },
      "InvitationProjectGrant": {
        "type": "object",
        "description": "A project grant bundled with an invitation, applied on accept.",
        "required": [
          "project",
          "role"
        ],
        "properties": {
          "project": {
            "description": "Project the grant applies to.",
            "$ref": "#/components/schemas/ProjectSummary"
          },
          "role": {
            "$ref": "#/components/schemas/ProjectRole"
          }
        },
        "example": {
          "project": {
            "id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
            "name": "Production",
            "created_at": "2024-01-15T10:30:00Z"
          },
          "role": "viewer"
        }
      },
      "Invitation": {
        "type": "object",
        "description": "A pending offer to join a workspace. An invitation can optionally bundle project grants. The invitee is identified by email because they may not have a Kratos account yet at the time the invitation is created.\n",
        "required": [
          "id",
          "workspace",
          "email",
          "workspace_role",
          "status",
          "expires_at",
          "created_at",
          "project_grants"
        ],
        "properties": {
          "id": {
            "description": "Unique invitation identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "workspace": {
            "description": "Workspace the invitee is being added to.",
            "$ref": "#/components/schemas/WorkspaceSummary"
          },
          "email": {
            "description": "Recipient email address.",
            "$ref": "#/components/schemas/Email"
          },
          "workspace_role": {
            "$ref": "#/components/schemas/AssignableWorkspaceRole"
          },
          "status": {
            "$ref": "#/components/schemas/InvitationStatus"
          },
          "expires_at": {
            "$ref": "#/components/schemas/ExpiresAt"
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          },
          "project_grants": {
            "type": "array",
            "description": "Project grants to apply when the invitation is accepted. Empty for admins, who receive implicit access to every project.\n",
            "items": {
              "$ref": "#/components/schemas/InvitationProjectGrant"
            }
          }
        },
        "example": {
          "id": "0193d4a1-7e02-7d29-a2b3-4c5d6e7f8901",
          "workspace": {
            "id": "550e8400-e29b-41d4-a716-446655440000",
            "name": "Acme Inc",
            "created_at": "2024-01-15T10:30:00Z"
          },
          "email": "user@example.com",
          "workspace_role": "member",
          "status": "pending",
          "expires_at": "2024-01-22T10:30:00Z",
          "created_at": "2024-01-15T10:30:00Z",
          "project_grants": [
            {
              "project": {
                "id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
                "name": "Production",
                "created_at": "2024-01-15T10:30:00Z"
              },
              "role": "viewer"
            }
          ]
        }
      },
      "ConflictProblem": {
        "type": "object",
        "description": "Problem details for conflict errors (409 Conflict).\n\nStandard problem response when request conflicts with current server state\nfollowing [RFC 7807](https://tools.ietf.org/rfc/rfc7807.txt).\n",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ProblemType",
            "example": "https://docs.vilna.io/apis/problems/conflict"
          },
          "title": {
            "$ref": "#/components/schemas/ProblemTitle",
            "example": "Conflict"
          },
          "status": {
            "$ref": "#/components/schemas/ProblemStatus",
            "example": 409
          },
          "detail": {
            "$ref": "#/components/schemas/ProblemDetail",
            "example": "Resource already exists with the same identifier"
          },
          "instance": {
            "$ref": "#/components/schemas/ProblemInstance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "example": "invoice.address_occupied"
          }
        }
      },
      "RpcStatus": {
        "type": "string",
        "enum": [
          "active",
          "deleting"
        ],
        "description": "Current lifecycle status of the RPC.",
        "x-enumDescriptions": {
          "active": "RPC is operational.",
          "deleting": "RPC is being deleted together with its workspace."
        },
        "example": "active"
      },
      "UpdatedAt": {
        "description": "Timestamp when the resource was last updated. RFC 3339 / ISO 8601, UTC.",
        "format": "date-time",
        "type": "string",
        "example": "2024-01-15T10:30:00Z"
      },
      "Rpc": {
        "type": "object",
        "description": "Workspace RPC access configuration. Provisioned automatically with every workspace and available to every workspace member. There is exactly one Rpc per workspace.\n",
        "required": [
          "id",
          "workspace_id",
          "status",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "description": "Unique RPC identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "workspace_id": {
            "description": "Workspace this RPC belongs to.",
            "$ref": "#/components/schemas/UUID"
          },
          "status": {
            "$ref": "#/components/schemas/RpcStatus"
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          },
          "updated_at": {
            "$ref": "#/components/schemas/UpdatedAt"
          }
        },
        "example": {
          "id": "0193d4a1-7e02-7d29-9a1b-5c6d7e8f9012",
          "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
          "status": "active",
          "created_at": "2024-01-15T10:30:00Z",
          "updated_at": "2024-01-15T10:30:00Z"
        }
      },
      "KeyName": {
        "type": "string",
        "maxLength": 32,
        "description": "Human-readable key name.",
        "example": "Production key"
      },
      "KeyPreview": {
        "type": "string",
        "minLength": 6,
        "maxLength": 6,
        "description": "First 6 characters of the random body, i.e. the 6 characters immediately after the `vilna_{type}_` prefix. For raw key `vilna_api_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5` the preview is `a1B2c3`. Safe to display in UIs for identifying a key without exposing the secret.\n",
        "example": "a1B2c3"
      },
      "RevokedAt": {
        "description": "Timestamp when the resource was revoked. RFC 3339 / ISO 8601, UTC. Absent if the resource is active.",
        "format": "date-time",
        "type": "string",
        "example": "2025-06-15T12:00:00Z"
      },
      "LastUsedAt": {
        "description": "Timestamp of the most recent successful authentication with this key. RFC 3339 / ISO 8601, UTC. Absent until the key has been used at least once.",
        "format": "date-time",
        "type": "string",
        "example": "2025-06-15T12:00:00Z"
      },
      "KeyBase": {
        "type": "object",
        "description": "Fields shared by all authentication key types.",
        "required": [
          "id",
          "name",
          "key_preview",
          "permissions",
          "created_at"
        ],
        "properties": {
          "id": {
            "description": "Unique key identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Raw permission strings granted to the key."
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          },
          "expires_at": {
            "$ref": "#/components/schemas/ExpiresAt"
          },
          "revoked_at": {
            "$ref": "#/components/schemas/RevokedAt"
          },
          "last_used_at": {
            "$ref": "#/components/schemas/LastUsedAt"
          }
        }
      },
      "RPCPermission": {
        "type": "string",
        "description": "Permission for workspace-scoped RPC keys.",
        "enum": [
          "rpc:call"
        ],
        "x-enumDescriptions": {
          "rpc:call": "Send JSON-RPC requests to blockchain nodes."
        },
        "example": "rpc:call"
      },
      "RpcKey": {
        "description": "A workspace-scoped RPC key. The raw secret is only shown at creation.",
        "allOf": [
          {
            "$ref": "#/components/schemas/KeyBase"
          },
          {
            "type": "object",
            "required": [
              "workspace_id",
              "permissions"
            ],
            "properties": {
              "workspace_id": {
                "description": "Workspace this key is scoped to.",
                "$ref": "#/components/schemas/UUID"
              },
              "permissions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/RPCPermission"
                },
                "description": "Permissions granted to this key."
              }
            }
          }
        ],
        "example": {
          "id": "0193d4a1-9f04-7e31-e7f8-901234567890",
          "name": "RPC service key",
          "key_preview": "a1B2c3",
          "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
          "permissions": [
            "rpc:call"
          ],
          "created_at": "2024-01-15T10:30:00Z"
        }
      },
      "RawKey": {
        "type": "string",
        "minLength": 40,
        "maxLength": 40,
        "pattern": "^vilna_(api|mgt|rpc)_[A-Za-z0-9]{30}$",
        "description": "The full secret key, 40 characters: `vilna_{type}_{body}` where `{type}`\nis `api`, `mgt`, or `rpc` and `{body}` is 30 base62 characters.\n**Returned only in the create response; store it securely.** The server\ndoes not store the secret and cannot return it again; lost keys must be\nrevoked and re-created.\n",
        "example": "vilna_api_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5"
      },
      "RpcKeyCreated": {
        "type": "object",
        "description": "Envelope for a newly issued RPC key. Contains the raw secret shown only once.",
        "required": [
          "item",
          "raw_key"
        ],
        "properties": {
          "item": {
            "$ref": "#/components/schemas/RpcKey"
          },
          "raw_key": {
            "$ref": "#/components/schemas/RawKey"
          }
        }
      },
      "LogEventType": {
        "type": "string",
        "description": "Discriminator for activity log event types.",
        "enum": [
          "workspace.created",
          "workspace.renamed",
          "workspace_member.joined",
          "workspace_member.role_changed",
          "workspace_member.removed",
          "project.created",
          "project.renamed",
          "project.deleted",
          "project_member.added",
          "project_member.role_changed",
          "project_member.removed",
          "invitation.created",
          "invitation.accepted",
          "invitation.declined",
          "invitation.revoked",
          "invitation.expired",
          "api_key.created",
          "api_key.revoked",
          "rpc_key.created",
          "rpc_key.revoked",
          "mgt_key.created",
          "mgt_key.revoked"
        ],
        "x-enumDescriptions": {
          "workspace.created": "Workspace was created.",
          "workspace.renamed": "Workspace name was changed.",
          "workspace_member.joined": "A user joined the workspace, either by accepting an invitation or as the owner at workspace creation.",
          "workspace_member.role_changed": "A workspace member's role was changed (`admin` or `member`).",
          "workspace_member.removed": "A member was removed from the workspace.",
          "project.created": "Project was created inside the workspace.",
          "project.renamed": "Project name was changed.",
          "project.deleted": "Project was deleted.",
          "project_member.added": "A workspace member was granted access to a project.",
          "project_member.role_changed": "A project member's role was changed (`editor` or `viewer`).",
          "project_member.removed": "A member's project access was revoked.",
          "invitation.created": "A workspace invitation was sent.",
          "invitation.accepted": "Invitation was accepted by the invitee.",
          "invitation.declined": "Invitation was declined by the invitee.",
          "invitation.revoked": "Invitation was cancelled by a workspace admin.",
          "invitation.expired": "Invitation was not answered before its expiration time.",
          "api_key.created": "A project-scoped API key was created.",
          "api_key.revoked": "An API key was revoked.",
          "rpc_key.created": "A workspace-scoped RPC key was created.",
          "rpc_key.revoked": "An RPC key was revoked.",
          "mgt_key.created": "A workspace-scoped management key was created.",
          "mgt_key.revoked": "A management key was revoked."
        },
        "example": "workspace.created"
      },
      "WorkspaceCreatedEventData": {
        "type": "object",
        "description": "Payload for `workspace.created`.",
        "required": [
          "type",
          "workspace_id",
          "workspace_name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workspace.created"
            ]
          },
          "workspace_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "workspace_name": {
            "type": "string",
            "description": "Workspace name at the time of the event.",
            "example": "My Workspace"
          }
        }
      },
      "WorkspaceRenamedEventData": {
        "type": "object",
        "description": "Payload for `workspace.renamed`.",
        "required": [
          "type",
          "workspace_id",
          "old_name",
          "new_name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workspace.renamed"
            ]
          },
          "workspace_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "old_name": {
            "type": "string",
            "description": "Workspace name before the rename.",
            "example": "Old Name"
          },
          "new_name": {
            "type": "string",
            "description": "Workspace name after the rename.",
            "example": "New Name"
          }
        }
      },
      "WorkspaceMemberJoinedEventData": {
        "type": "object",
        "description": "Payload for `workspace_member.joined`.",
        "required": [
          "type",
          "user_id",
          "role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workspace_member.joined"
            ]
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "role": {
            "$ref": "#/components/schemas/WorkspaceRole"
          }
        }
      },
      "WorkspaceMemberRoleChangedEventData": {
        "type": "object",
        "description": "Payload for `workspace_member.role_changed`.",
        "required": [
          "type",
          "user_id",
          "old_role",
          "new_role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workspace_member.role_changed"
            ]
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "old_role": {
            "$ref": "#/components/schemas/WorkspaceRole"
          },
          "new_role": {
            "$ref": "#/components/schemas/WorkspaceRole"
          }
        }
      },
      "WorkspaceMemberRemovedEventData": {
        "type": "object",
        "description": "Payload for `workspace_member.removed`.",
        "required": [
          "type",
          "user_id",
          "role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workspace_member.removed"
            ]
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "role": {
            "$ref": "#/components/schemas/WorkspaceRole"
          }
        }
      },
      "ProjectCreatedEventData": {
        "type": "object",
        "description": "Payload for `project.created`.",
        "required": [
          "type",
          "project_id",
          "project_name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project.created"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "project_name": {
            "type": "string",
            "description": "Project name at the time of the event.",
            "example": "Production"
          }
        }
      },
      "ProjectRenamedEventData": {
        "type": "object",
        "description": "Payload for `project.renamed`.",
        "required": [
          "type",
          "project_id",
          "old_name",
          "new_name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project.renamed"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "old_name": {
            "type": "string",
            "description": "Project name before the rename.",
            "example": "Old"
          },
          "new_name": {
            "type": "string",
            "description": "Project name after the rename.",
            "example": "New"
          }
        }
      },
      "ProjectDeletedEventData": {
        "type": "object",
        "description": "Payload for `project.deleted`.",
        "required": [
          "type",
          "project_id",
          "project_name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project.deleted"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "project_name": {
            "type": "string",
            "description": "Project name at the time of deletion.",
            "example": "Production"
          }
        }
      },
      "ProjectMemberAddedEventData": {
        "type": "object",
        "description": "Payload for `project_member.added`.",
        "required": [
          "type",
          "project_id",
          "user_id",
          "role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project_member.added"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "role": {
            "$ref": "#/components/schemas/ProjectRole"
          }
        }
      },
      "ProjectMemberRoleChangedEventData": {
        "type": "object",
        "description": "Payload for `project_member.role_changed`.",
        "required": [
          "type",
          "project_id",
          "user_id",
          "old_role",
          "new_role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project_member.role_changed"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "old_role": {
            "$ref": "#/components/schemas/ProjectRole"
          },
          "new_role": {
            "$ref": "#/components/schemas/ProjectRole"
          }
        }
      },
      "ProjectMemberRemovedEventData": {
        "type": "object",
        "description": "Payload for `project_member.removed`.",
        "required": [
          "type",
          "project_id",
          "user_id",
          "role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "project_member.removed"
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "user_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "role": {
            "$ref": "#/components/schemas/ProjectRole"
          }
        }
      },
      "InvitationCreatedEventData": {
        "type": "object",
        "description": "Payload for `invitation.created`.",
        "required": [
          "type",
          "invitation_id",
          "recipient_email",
          "workspace_role"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invitation.created"
            ]
          },
          "invitation_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "recipient_email": {
            "$ref": "#/components/schemas/Email"
          },
          "workspace_role": {
            "$ref": "#/components/schemas/AssignableWorkspaceRole"
          },
          "project_grants": {
            "type": "array",
            "description": "Bundled project grants the invitation will apply on accept.",
            "items": {
              "$ref": "#/components/schemas/InvitationProjectGrant"
            }
          }
        }
      },
      "InvitationAcceptedEventData": {
        "type": "object",
        "description": "Payload for `invitation.accepted`.",
        "required": [
          "type",
          "invitation_id",
          "recipient_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invitation.accepted"
            ]
          },
          "invitation_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "recipient_id": {
            "$ref": "#/components/schemas/UUID"
          }
        }
      },
      "InvitationDeclinedEventData": {
        "type": "object",
        "description": "Payload for `invitation.declined`.",
        "required": [
          "type",
          "invitation_id",
          "recipient_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invitation.declined"
            ]
          },
          "invitation_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "recipient_id": {
            "$ref": "#/components/schemas/UUID"
          }
        }
      },
      "InvitationRevokedEventData": {
        "type": "object",
        "description": "Payload for `invitation.revoked`.",
        "required": [
          "type",
          "invitation_id",
          "recipient_email"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invitation.revoked"
            ]
          },
          "invitation_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "recipient_email": {
            "$ref": "#/components/schemas/Email"
          }
        }
      },
      "InvitationExpiredEventData": {
        "type": "object",
        "description": "Payload for `invitation.expired`.",
        "required": [
          "type",
          "invitation_id",
          "recipient_email"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invitation.expired"
            ]
          },
          "invitation_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "recipient_email": {
            "$ref": "#/components/schemas/Email"
          }
        }
      },
      "ApiKeyCreatedEventData": {
        "type": "object",
        "description": "Payload for `api_key.created`.",
        "required": [
          "type",
          "key_id",
          "project_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "api_key.created"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "ApiKeyRevokedEventData": {
        "type": "object",
        "description": "Payload for `api_key.revoked`.",
        "required": [
          "type",
          "key_id",
          "project_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "api_key.revoked"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "project_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "RpcKeyCreatedEventData": {
        "type": "object",
        "description": "Payload for `rpc_key.created`.",
        "required": [
          "type",
          "key_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "rpc_key.created"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "RpcKeyRevokedEventData": {
        "type": "object",
        "description": "Payload for `rpc_key.revoked`.",
        "required": [
          "type",
          "key_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "rpc_key.revoked"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "MgtKeyCreatedEventData": {
        "type": "object",
        "description": "Payload for `mgt_key.created`.",
        "required": [
          "type",
          "key_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "mgt_key.created"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "MgtKeyRevokedEventData": {
        "type": "object",
        "description": "Payload for `mgt_key.revoked`.",
        "required": [
          "type",
          "key_id",
          "key_name",
          "key_preview"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "mgt_key.revoked"
            ]
          },
          "key_id": {
            "$ref": "#/components/schemas/UUID"
          },
          "key_name": {
            "$ref": "#/components/schemas/KeyName"
          },
          "key_preview": {
            "$ref": "#/components/schemas/KeyPreview"
          }
        }
      },
      "LogEvent": {
        "type": "object",
        "description": "An entry in the workspace activity feed. Each entry carries a denormalized snapshot of the referenced entities so the feed remains intelligible after those entities are renamed or deleted.\n",
        "required": [
          "workspace_id",
          "type",
          "data",
          "created_at"
        ],
        "properties": {
          "workspace_id": {
            "description": "Workspace the event belongs to.",
            "$ref": "#/components/schemas/UUID"
          },
          "actor_id": {
            "description": "User UUID that produced the event. Absent for system-emitted events.",
            "$ref": "#/components/schemas/UUID"
          },
          "type": {
            "$ref": "#/components/schemas/LogEventType"
          },
          "data": {
            "description": "Event-specific payload. The `type` field inside the payload echoes the top-level `type` and acts as the discriminator; switch on it to get a typed `data` shape (e.g. `project.renamed` yields `{ old_name, new_name, ... }`). Payload shapes are documented per event type in this schema.\n",
            "oneOf": [
              {
                "$ref": "#/components/schemas/WorkspaceCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/WorkspaceRenamedEventData"
              },
              {
                "$ref": "#/components/schemas/WorkspaceMemberJoinedEventData"
              },
              {
                "$ref": "#/components/schemas/WorkspaceMemberRoleChangedEventData"
              },
              {
                "$ref": "#/components/schemas/WorkspaceMemberRemovedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectRenamedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectDeletedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectMemberAddedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectMemberRoleChangedEventData"
              },
              {
                "$ref": "#/components/schemas/ProjectMemberRemovedEventData"
              },
              {
                "$ref": "#/components/schemas/InvitationCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/InvitationAcceptedEventData"
              },
              {
                "$ref": "#/components/schemas/InvitationDeclinedEventData"
              },
              {
                "$ref": "#/components/schemas/InvitationRevokedEventData"
              },
              {
                "$ref": "#/components/schemas/InvitationExpiredEventData"
              },
              {
                "$ref": "#/components/schemas/ApiKeyCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/ApiKeyRevokedEventData"
              },
              {
                "$ref": "#/components/schemas/RpcKeyCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/RpcKeyRevokedEventData"
              },
              {
                "$ref": "#/components/schemas/MgtKeyCreatedEventData"
              },
              {
                "$ref": "#/components/schemas/MgtKeyRevokedEventData"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "workspace.created": "#/components/schemas/WorkspaceCreatedEventData",
                "workspace.renamed": "#/components/schemas/WorkspaceRenamedEventData",
                "workspace_member.joined": "#/components/schemas/WorkspaceMemberJoinedEventData",
                "workspace_member.role_changed": "#/components/schemas/WorkspaceMemberRoleChangedEventData",
                "workspace_member.removed": "#/components/schemas/WorkspaceMemberRemovedEventData",
                "project.created": "#/components/schemas/ProjectCreatedEventData",
                "project.renamed": "#/components/schemas/ProjectRenamedEventData",
                "project.deleted": "#/components/schemas/ProjectDeletedEventData",
                "project_member.added": "#/components/schemas/ProjectMemberAddedEventData",
                "project_member.role_changed": "#/components/schemas/ProjectMemberRoleChangedEventData",
                "project_member.removed": "#/components/schemas/ProjectMemberRemovedEventData",
                "invitation.created": "#/components/schemas/InvitationCreatedEventData",
                "invitation.accepted": "#/components/schemas/InvitationAcceptedEventData",
                "invitation.declined": "#/components/schemas/InvitationDeclinedEventData",
                "invitation.revoked": "#/components/schemas/InvitationRevokedEventData",
                "invitation.expired": "#/components/schemas/InvitationExpiredEventData",
                "api_key.created": "#/components/schemas/ApiKeyCreatedEventData",
                "api_key.revoked": "#/components/schemas/ApiKeyRevokedEventData",
                "rpc_key.created": "#/components/schemas/RpcKeyCreatedEventData",
                "rpc_key.revoked": "#/components/schemas/RpcKeyRevokedEventData",
                "mgt_key.created": "#/components/schemas/MgtKeyCreatedEventData",
                "mgt_key.revoked": "#/components/schemas/MgtKeyRevokedEventData"
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the event was emitted.",
            "example": "2024-01-15T10:30:00Z"
          }
        }
      },
      "LogEventReferences": {
        "type": "object",
        "description": "Entities referenced by events in this page, keyed by ID.",
        "required": [
          "users"
        ],
        "properties": {
          "users": {
            "type": "object",
            "description": "Users referenced by events in this page, keyed by user ID.",
            "propertyNames": {
              "$ref": "#/components/schemas/UUID"
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/User"
            }
          }
        },
        "example": {
          "users": {}
        }
      },
      "ProjectStatus": {
        "type": "string",
        "enum": [
          "active",
          "deleting"
        ],
        "description": "Current lifecycle status of the project.",
        "x-enumDescriptions": {
          "active": "Project is operational.",
          "deleting": "Project is being deleted. Mutations are rejected; reads may still return the record until cleanup finishes."
        },
        "example": "active"
      },
      "Project": {
        "type": "object",
        "description": "A project within a workspace. Projects scope API keys and member grants.",
        "required": [
          "id",
          "workspace_id",
          "name",
          "status",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "description": "Unique project identifier.",
            "$ref": "#/components/schemas/UUID"
          },
          "workspace_id": {
            "description": "Workspace this project belongs to.",
            "$ref": "#/components/schemas/UUID"
          },
          "name": {
            "$ref": "#/components/schemas/ProjectName"
          },
          "status": {
            "$ref": "#/components/schemas/ProjectStatus"
          },
          "created_at": {
            "$ref": "#/components/schemas/CreatedAt"
          },
          "updated_at": {
            "$ref": "#/components/schemas/UpdatedAt"
          }
        },
        "example": {
          "id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
          "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
          "name": "Production",
          "status": "active",
          "created_at": "2024-01-15T10:30:00Z",
          "updated_at": "2024-01-15T10:30:00Z"
        }
      },
      "ProjectMember": {
        "type": "object",
        "description": "A workspace member's explicit role assignment within a specific project. Workspace admins have implicit access to every project and are not listed.\n",
        "required": [
          "user",
          "role",
          "granted_at"
        ],
        "properties": {
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "role": {
            "$ref": "#/components/schemas/ProjectRole"
          },
          "granted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the grant was issued.",
            "example": "2024-01-15T10:30:00Z"
          }
        },
        "example": {
          "user": {
            "id": "0193d4a1-8f03-7e30-b4c5-6d7e8f901234",
            "email": "user@example.com",
            "first_name": "John",
            "last_name": "Doe",
            "avatar": "https://cdn.vilna.io/avatars/0193d4a1.jpg"
          },
          "role": "editor",
          "granted_at": "2024-01-15T10:30:00Z"
        }
      },
      "APIPermission": {
        "type": "string",
        "description": "Permission for project-scoped API keys.",
        "enum": [
          "api:address:read",
          "api:address:write",
          "api:address:delete",
          "api:transaction:read",
          "api:blockchain:read",
          "api:balance:read",
          "api:asset:read",
          "api:asset:write",
          "api:simulate:call",
          "api:subscription:read",
          "api:subscription:write",
          "api:subscription:delete",
          "api:channel:read",
          "api:channel:write",
          "api:channel:delete",
          "api:public_key:read",
          "api:public_key:write",
          "api:public_key:delete",
          "api:invoice:read",
          "api:invoice:write",
          "api:invoice:delete",
          "api:token_tag:read",
          "api:token_tag:write",
          "api:token_tag:delete",
          "api:address_tag:read",
          "api:address_tag:write",
          "api:address_tag:delete"
        ],
        "x-enumDescriptions": {
          "api:address:read": "List and view tracked addresses.",
          "api:address:write": "Import and update addresses.",
          "api:address:delete": "Remove tracked addresses.",
          "api:transaction:read": "List and view transactions and activity.",
          "api:blockchain:read": "List supported blockchains.",
          "api:balance:read": "View address balances and snapshots.",
          "api:asset:read": "List and view token metadata.",
          "api:asset:write": "Update token metadata.",
          "api:simulate:call": "Simulate transactions on supported chains.",
          "api:subscription:read": "List and view notification subscriptions.",
          "api:subscription:write": "Create and update notification subscriptions.",
          "api:subscription:delete": "Delete notification subscriptions.",
          "api:channel:read": "List notification channels and delivery logs.",
          "api:channel:write": "Create, update, and test notification channels.",
          "api:channel:delete": "Delete notification channels.",
          "api:public_key:read": "List and view extended public keys.",
          "api:public_key:write": "Register and update extended public keys.",
          "api:public_key:delete": "Remove extended public keys.",
          "api:invoice:read": "List and view invoices.",
          "api:invoice:write": "Create and cancel invoices.",
          "api:invoice:delete": "Delete invoices.",
          "api:token_tag:read": "List and view token tags.",
          "api:token_tag:write": "Create and update token tags.",
          "api:token_tag:delete": "Delete token tags.",
          "api:address_tag:read": "List and view address tags.",
          "api:address_tag:write": "Create and update address tags.",
          "api:address_tag:delete": "Delete address tags."
        },
        "example": "api:address:read"
      },
      "ApiKey": {
        "description": "A project-scoped API key. The raw secret is only shown at creation.",
        "allOf": [
          {
            "$ref": "#/components/schemas/KeyBase"
          },
          {
            "type": "object",
            "required": [
              "workspace_id",
              "project_id",
              "permissions"
            ],
            "properties": {
              "workspace_id": {
                "description": "Workspace the key's project belongs to. Populated for convenience; always matches the project's workspace.",
                "$ref": "#/components/schemas/UUID"
              },
              "project_id": {
                "description": "Project this key is scoped to.",
                "$ref": "#/components/schemas/UUID"
              },
              "permissions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/APIPermission"
                },
                "description": "Permissions granted to this key."
              }
            }
          }
        ],
        "example": {
          "id": "0193d4a1-9f04-7e31-c5d6-7e8f90123456",
          "name": "Backend service key",
          "key_preview": "a1B2c3",
          "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
          "project_id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
          "permissions": [
            "api:address:read",
            "api:address:write"
          ],
          "created_at": "2024-01-15T10:30:00Z"
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "description": "Envelope for a newly issued API key. Contains the raw secret shown only once.",
        "required": [
          "item",
          "raw_key"
        ],
        "properties": {
          "item": {
            "$ref": "#/components/schemas/ApiKey"
          },
          "raw_key": {
            "$ref": "#/components/schemas/RawKey"
          }
        }
      },
      "VersionInfo": {
        "type": "object",
        "description": "API version information.",
        "properties": {
          "version": {
            "description": "API version (semantic versioning).",
            "type": "string"
          }
        },
        "required": [
          "version"
        ],
        "example": {
          "version": "1.0.0"
        }
      }
    },
    "parameters": {
      "workspaceID": {
        "name": "workspace_id",
        "in": "path",
        "description": "Unique identifier (UUID) of the workspace.",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "page": {
        "description": "1-based page index. Defaults to `1` when omitted.",
        "in": "query",
        "name": "page",
        "required": false,
        "schema": {
          "default": 1,
          "example": 1,
          "minimum": 1,
          "type": "integer"
        }
      },
      "limit": {
        "description": "Page size. Defaults to `30`, capped at `100`.",
        "in": "query",
        "name": "limit",
        "required": false,
        "schema": {
          "default": 30,
          "example": 20,
          "maximum": 100,
          "minimum": 1,
          "type": "integer"
        }
      },
      "sortWorkspaceMembers": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "role",
            "-role",
            "joined_at",
            "-joined_at"
          ],
          "default": "-joined_at",
          "example": "joined_at"
        }
      },
      "workspaceMembersFilterRole": {
        "name": "role",
        "in": "query",
        "description": "Filter workspace members by role.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WorkspaceRole"
          }
        },
        "example": [
          "admin"
        ]
      },
      "workspaceMembersFilterSearch": {
        "name": "search",
        "in": "query",
        "description": "Filter workspace members by email (partial match, case-insensitive).",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 32,
          "example": "john@"
        }
      },
      "userID": {
        "name": "user_id",
        "in": "path",
        "description": "Unique identifier (UUID) of the user.",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "sortInvitations": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "status",
            "-status",
            "expires_at",
            "-expires_at",
            "created_at",
            "-created_at"
          ],
          "default": "-created_at",
          "example": "created_at"
        }
      },
      "invitationsFilterStatus": {
        "name": "status",
        "in": "query",
        "description": "Filter invitations by status.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/InvitationStatus"
          }
        },
        "example": [
          "pending"
        ]
      },
      "invitationID": {
        "name": "invitation_id",
        "in": "path",
        "description": "Unique identifier (UUID) of the invitation.",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "sortAuthKeys": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "name",
            "-name",
            "created_at",
            "-created_at",
            "revoked_at",
            "-revoked_at",
            "last_used_at",
            "-last_used_at"
          ],
          "default": "-created_at",
          "example": "created_at"
        }
      },
      "rpcKeysFilterStatus": {
        "name": "status",
        "in": "query",
        "description": "Filter RPC keys by lifecycle status.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "active",
              "revoked"
            ]
          }
        },
        "example": [
          "active"
        ]
      },
      "rpcKeysFilterSearch": {
        "name": "search",
        "in": "query",
        "description": "Filter RPC keys by name (partial match, case-insensitive).",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 32,
          "example": "production"
        }
      },
      "keyID": {
        "name": "key_id",
        "in": "path",
        "description": "UUID of the key, as returned by the create or list endpoint for this resource. Not the raw secret.",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "sortLogs": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "created_at",
            "-created_at"
          ],
          "default": "-created_at",
          "example": "created_at"
        }
      },
      "logsFilterType": {
        "name": "type",
        "in": "query",
        "description": "Filter log events by type.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/LogEventType"
          }
        },
        "example": [
          "workspace.created"
        ]
      },
      "logsFilterActorID": {
        "name": "actor_id",
        "in": "query",
        "description": "Filter log events by actor user UUID.",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "logsFilterFrom": {
        "name": "from",
        "in": "query",
        "description": "Return only events emitted at or after this timestamp.",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2024-01-01T00:00:00Z"
        }
      },
      "logsFilterTo": {
        "name": "to",
        "in": "query",
        "description": "Return only events emitted before this timestamp.",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2024-02-01T00:00:00Z"
        }
      },
      "sortProjects": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "name",
            "-name",
            "created_at",
            "-created_at",
            "updated_at",
            "-updated_at"
          ],
          "default": "-created_at",
          "example": "created_at"
        }
      },
      "projectsFilterStatus": {
        "name": "status",
        "in": "query",
        "description": "Filter projects by status.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProjectStatus"
          }
        },
        "example": [
          "active"
        ]
      },
      "projectsFilterSearch": {
        "name": "search",
        "in": "query",
        "description": "Filter projects by name (partial match, case-insensitive).",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 32,
          "example": "production"
        }
      },
      "projectID": {
        "name": "project_id",
        "in": "path",
        "description": "Unique identifier (UUID) of the project.",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/UUID"
        }
      },
      "sortProjectMembers": {
        "name": "sort_by",
        "in": "query",
        "description": "Sort field. Prefix with `-` for descending order (e.g. `-created_at`).",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "role",
            "-role",
            "granted_at",
            "-granted_at"
          ],
          "default": "-granted_at",
          "example": "granted_at"
        }
      },
      "projectMembersFilterRole": {
        "name": "role",
        "in": "query",
        "description": "Filter project members by role.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/ProjectRole"
          }
        },
        "example": [
          "editor"
        ]
      },
      "projectMembersFilterSearch": {
        "name": "search",
        "in": "query",
        "description": "Filter project members by email (partial match, case-insensitive).",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 32,
          "example": "john@"
        }
      },
      "apiKeysFilterStatus": {
        "name": "status",
        "in": "query",
        "description": "Filter API keys by lifecycle status.",
        "required": false,
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "active",
              "revoked"
            ]
          }
        },
        "example": [
          "active"
        ]
      },
      "apiKeysFilterSearch": {
        "name": "search",
        "in": "query",
        "description": "Filter API keys by name (partial match, case-insensitive).",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 32,
          "example": "production"
        }
      }
    },
    "responses": {
      "problem": {
        "description": "Unexpected error.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "workspace_members_list_response": {
        "description": "Paginated list of workspace members.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkspaceMember"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "invalid_request_problem": {
        "description": "Bad request (e.g., missing or invalid fields).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/InvalidRequestProblem"
            },
            "examples": {
              "name_too_long": {
                "summary": "A name field exceeds its maximum length",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/invalid-request",
                  "title": "Invalid Request",
                  "status": 400,
                  "code": "resource.name_too_long",
                  "detail": "resource name exceeds maximum length",
                  "instance": "/traces/0199ce90-1a2b-7c01-9c2a-9d0010eaa300",
                  "fields": [
                    {
                      "name": "name",
                      "reason": "must not exceed 64 characters"
                    }
                  ]
                }
              },
              "invalid_role": {
                "summary": "An invalid member role was supplied",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/invalid-request",
                  "title": "Invalid Request",
                  "status": 400,
                  "code": "member.role_invalid",
                  "detail": "member role is invalid (allowed: admin, member)",
                  "instance": "/traces/0199ce90-4c5d-7c01-9c2a-9d0010eaa301"
                }
              },
              "invalid_pagination": {
                "summary": "A pagination argument is out of range",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/invalid-request",
                  "title": "Invalid Request",
                  "status": 400,
                  "code": "shared.pagination_invalid",
                  "detail": "invalid pagination arguments",
                  "instance": "/traces/0199ce90-7e8f-7c01-9c2a-9d0010eaa302"
                }
              }
            }
          }
        }
      },
      "unauthorized_problem": {
        "description": "Missing or invalid authentication credentials.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/UnauthorizedProblem"
            },
            "examples": {
              "missing_credentials": {
                "summary": "No valid management key or session was supplied",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/unauthorized",
                  "title": "Unauthorized",
                  "status": 401,
                  "code": "unspecified",
                  "detail": "You are not authorized to access this resource. If the problem persists, please contact our support team — your feedback helps us improve.",
                  "instance": "/traces/0199ce94-1a2b-7c01-9c2a-9d0010eaa340"
                }
              }
            }
          }
        }
      },
      "forbidden_problem": {
        "description": "Insufficient permissions.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ForbiddenProblem"
            },
            "examples": {
              "insufficient_permissions": {
                "summary": "The management key lacks the required permission",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/forbidden",
                  "title": "Forbidden",
                  "status": 403,
                  "code": "unspecified",
                  "detail": "Your credentials are valid but don't include the permission this operation needs. Check the management key permissions in the dashboard. Permissions are set when the key is created and can't be edited later. To change them, create a new key.",
                  "instance": "/forbidden?method=createWorkspaceProject"
                }
              }
            }
          }
        }
      },
      "not_found_problem": {
        "description": "Requested resource does not exist.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/NotFoundProblem"
            },
            "examples": {
              "resource_not_found": {
                "summary": "The workspace or project does not exist",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/not-found",
                  "title": "Not Found",
                  "status": 404,
                  "code": "resource.not_found",
                  "detail": "resource not found",
                  "instance": "/traces/0199ce91-1a2b-7c01-9c2a-9d0010eaa310"
                }
              },
              "member_not_found": {
                "summary": "The workspace member does not exist",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/not-found",
                  "title": "Not Found",
                  "status": 404,
                  "code": "member.not_found",
                  "detail": "workspace member not found",
                  "instance": "/traces/0199ce91-4c5d-7c01-9c2a-9d0010eaa311"
                }
              }
            }
          }
        }
      },
      "no_content_response": {
        "description": "Successful operation with no response body."
      },
      "workspace_member_response": {
        "description": "Single workspace member.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/WorkspaceMember"
                }
              }
            }
          }
        }
      },
      "precondition_problem": {
        "description": "Request preconditions were not met.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/PreconditionProblem"
            },
            "examples": {
              "key_limit_exceeded": {
                "summary": "The key count limit for this scope has been reached",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/precondition",
                  "title": "Precondition Failed",
                  "status": 422,
                  "code": "auth_key.resource_limit_exceeded",
                  "detail": "key count limit exceeded for scope",
                  "instance": "/traces/0199ce93-1a2b-7c01-9c2a-9d0010eaa330"
                }
              }
            }
          }
        }
      },
      "invitations_list_response": {
        "description": "Paginated list of invitations.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Invitation"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "invitation_response": {
        "description": "Single invitation.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/Invitation"
                }
              }
            }
          }
        }
      },
      "conflict_problem": {
        "description": "Request conflicts with the current resource state.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ConflictProblem"
            },
            "examples": {
              "member_already_exists": {
                "summary": "The user is already a member of the workspace",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/conflict",
                  "title": "Conflict",
                  "status": 409,
                  "code": "member.already_exists",
                  "detail": "user is already a member of this workspace",
                  "instance": "/traces/0199ce92-1a2b-7c01-9c2a-9d0010eaa320"
                }
              },
              "last_admin": {
                "summary": "Cannot remove or demote the workspace's last admin",
                "value": {
                  "type": "https://docs.vilna.io/apis/problems/conflict",
                  "title": "Conflict",
                  "status": 409,
                  "code": "workspace.last_admin",
                  "detail": "cannot demote or remove the last admin of the workspace",
                  "instance": "/traces/0199ce92-4c5d-7c01-9c2a-9d0010eaa321"
                }
              }
            }
          }
        }
      },
      "rpc_response": {
        "description": "Workspace RPC configuration.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/Rpc"
                }
              }
            }
          }
        }
      },
      "rpc_keys_list_response": {
        "description": "Paginated list of RPC keys.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RpcKey"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "rpc_key_created_response": {
        "description": "Newly created RPC key with raw secret (shown once).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RpcKeyCreated"
            }
          }
        }
      },
      "rpc_key_response": {
        "description": "Single workspace RPC key.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/RpcKey"
                }
              }
            }
          }
        }
      },
      "log_events_list_response": {
        "description": "Paginated activity feed.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "references",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LogEvent"
                  }
                },
                "references": {
                  "$ref": "#/components/schemas/LogEventReferences"
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "projects_list_response": {
        "description": "Paginated list of projects.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "project_response": {
        "description": "Single project.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          }
        }
      },
      "project_members_list_response": {
        "description": "Paginated list of project member grants.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProjectMember"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "project_member_response": {
        "description": "Single project member grant.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/ProjectMember"
                }
              }
            }
          }
        }
      },
      "api_keys_list_response": {
        "description": "Paginated list of API keys.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "items",
                "meta"
              ],
              "properties": {
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKey"
                  }
                },
                "meta": {
                  "$ref": "#/components/schemas/PaginationMeta"
                }
              }
            }
          }
        }
      },
      "api_key_created_response": {
        "description": "Newly created API key with raw secret (shown once).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiKeyCreated"
            }
          }
        }
      },
      "api_key_response": {
        "description": "Single project API key.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "item"
              ],
              "properties": {
                "item": {
                  "$ref": "#/components/schemas/ApiKey"
                }
              }
            }
          }
        }
      },
      "version_response": {
        "description": "Service version info.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/VersionInfo"
            }
          }
        }
      }
    },
    "requestBodies": {
      "update_workspace_member_request": {
        "description": "Workspace member role update payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "role"
              ],
              "properties": {
                "role": {
                  "$ref": "#/components/schemas/AssignableWorkspaceRole"
                }
              },
              "example": {
                "role": "admin"
              }
            }
          }
        }
      },
      "create_invitation_request": {
        "description": "Workspace invitation creation payload. `project_grants` may only accompany `workspace_role: member`; admins receive implicit access to every project.\n",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "email",
                "workspace_role"
              ],
              "properties": {
                "email": {
                  "description": "Email address of the invited user.",
                  "$ref": "#/components/schemas/Email"
                },
                "workspace_role": {
                  "$ref": "#/components/schemas/AssignableWorkspaceRole"
                },
                "project_grants": {
                  "type": "array",
                  "description": "Optional project grants to apply when the invitation is accepted.",
                  "items": {
                    "type": "object",
                    "required": [
                      "project_id",
                      "role"
                    ],
                    "properties": {
                      "project_id": {
                        "description": "Project the grant is for.",
                        "$ref": "#/components/schemas/UUID"
                      },
                      "role": {
                        "$ref": "#/components/schemas/ProjectRole"
                      }
                    }
                  }
                }
              },
              "example": {
                "email": "user@example.com",
                "workspace_role": "member",
                "project_grants": [
                  {
                    "project_id": "0193d4a1-7e02-7d29-8d8a-3b0e5a7c8f12",
                    "role": "viewer"
                  }
                ]
              }
            }
          }
        }
      },
      "create_rpc_key_request": {
        "description": "RPC key creation payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "name",
                "permissions"
              ],
              "properties": {
                "name": {
                  "$ref": "#/components/schemas/KeyName"
                },
                "permissions": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RPCPermission"
                  },
                  "minItems": 1,
                  "description": "Permissions to grant. Must all belong to the `rpc:*` scope."
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Optional expiration timestamp. Omit to create a non-expiring key.",
                  "example": "2025-01-15T10:30:00Z"
                }
              },
              "example": {
                "name": "RPC service key",
                "permissions": [
                  "rpc:call"
                ],
                "expires_at": "2025-01-15T10:30:00Z"
              }
            }
          }
        }
      },
      "create_project_request": {
        "description": "Project creation payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "$ref": "#/components/schemas/ProjectName"
                }
              },
              "example": {
                "name": "Production"
              }
            }
          }
        }
      },
      "update_project_request": {
        "description": "Project update payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "$ref": "#/components/schemas/ProjectName"
                }
              },
              "example": {
                "name": "Renamed Project"
              }
            }
          }
        }
      },
      "create_project_member_request": {
        "description": "Project grant creation payload. The target user must already be a workspace member.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "user_id",
                "role"
              ],
              "properties": {
                "user_id": {
                  "description": "User UUID of an existing workspace member.",
                  "$ref": "#/components/schemas/UUID"
                },
                "role": {
                  "$ref": "#/components/schemas/ProjectRole"
                }
              },
              "example": {
                "user_id": "0193d4a1-8f03-7e30-b4c5-6d7e8f901234",
                "role": "viewer"
              }
            }
          }
        }
      },
      "update_project_member_request": {
        "description": "Project grant role update payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "role"
              ],
              "properties": {
                "role": {
                  "$ref": "#/components/schemas/ProjectRole"
                }
              },
              "example": {
                "role": "editor"
              }
            }
          }
        }
      },
      "create_api_key_request": {
        "description": "API key creation payload.",
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "name",
                "permissions"
              ],
              "properties": {
                "name": {
                  "$ref": "#/components/schemas/KeyName"
                },
                "permissions": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/APIPermission"
                  },
                  "minItems": 1,
                  "description": "Permissions to grant. Must all belong to the `api:*` scope."
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Optional expiration timestamp. Omit to create a non-expiring key.",
                  "example": "2025-01-15T10:30:00Z"
                }
              },
              "example": {
                "name": "Backend service key",
                "permissions": [
                  "api:address:read",
                  "api:address:write"
                ],
                "expires_at": "2025-01-15T10:30:00Z"
              }
            }
          }
        }
      }
    }
  },
  "x-keywords": {
    "includes": [
      "management api",
      "workspace management",
      "api key management",
      "team management"
    ],
    "excludes": [
      "blockchain data",
      "transaction monitoring",
      "wallet balance",
      "address monitoring",
      "webhook",
      "crypto payment"
    ]
  },
  "x-tagGroups": [
    {
      "name": "Workspace",
      "tags": [
        "member",
        "invitation",
        "log"
      ]
    },
    {
      "name": "Projects",
      "tags": [
        "project",
        "project_member"
      ]
    },
    {
      "name": "RPC",
      "tags": [
        "rpc"
      ]
    },
    {
      "name": "Key Management",
      "tags": [
        "api_key",
        "rpc_key"
      ]
    },
    {
      "name": "Developer Tools",
      "tags": [
        "version"
      ]
    }
  ]
}