{
 "openapi": "3.0.3",
 "info": {
  "title": "Bramble WiKi API",
  "version": "2026-11-13",
  "description": "Bramble WiKi, the knowledge base: spaces, collections and articles with revisions, tags, comments, images and permissions. Works with an API key.\n"
 },
 "servers": [
  {
   "url": "https://{org}.brambleit.cloud/api",
   "variables": {
    "org": {
     "default": "your-org"
    }
   }
  }
 ],
 "components": {
  "securitySchemes": {
   "apiKey": {
    "type": "apiKey",
    "in": "header",
    "name": "X-API-Key"
   },
   "session": {
    "type": "apiKey",
    "in": "cookie",
    "name": "sso_session"
   },
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "JWT"
   }
  }
 },
 "tags": [
  {
   "name": "Spaces",
   "description": "Top-level areas of the wiki."
  },
  {
   "name": "Collections",
   "description": "Groups of articles within a space."
  },
  {
   "name": "Articles",
   "description": "Articles, their revisions, comments and tags."
  },
  {
   "name": "Permissions",
   "description": "Who can read or edit spaces and collections."
  },
  {
   "name": "Search & stats",
   "description": "Searching the wiki and usage statistics."
  },
  {
   "name": "Images",
   "description": "Images used in articles, spaces and collections."
  },
  {
   "name": "Admin",
   "description": "WiKi administration."
  }
 ],
 "paths": {
  "/v1/app/kb/images/{id}": {
   "get": {
    "tags": [
     "Images"
    ],
    "summary": "Serve image by ID (no auth required so <img> tags work)",
    "operationId": "get-v1-app-kb-images-id",
    "description": "Serve image by ID (no auth required so <img> tags work). Registered before the license gate below so it's resolved directly and never reaches it — every other route in this file is defined after the gate and stays covered by it regardless.\n\nRequires: None: public, or protected by a token in the address or body.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "File, page or redirect"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/me": {
   "get": {
    "tags": [
     "Search & stats"
    ],
    "summary": "Current user's identity + personal space status (used by frontend)",
    "operationId": "get-v1-app-kb-me",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "integer"
          },
          "name": {
           "type": "string"
          },
          "email": {
           "type": "string"
          },
          "isGlobalAdmin": {},
          "personalSpace": {
           "type": "object",
           "nullable": true,
           "properties": {
            "id": {
             "type": "integer"
            },
            "slug": {
             "type": "string"
            },
            "name": {
             "type": "string"
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/spaces": {
   "get": {
    "tags": [
     "Spaces"
    ],
    "summary": "Spaces (role-based visibility) GET all spaces (role-based visibility)",
    "operationId": "get-v1-app-kb-spaces",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "spaces": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "description": {
              "type": "string",
              "nullable": true
             },
             "color_hex": {
              "type": "string",
              "nullable": true
             },
             "icon_emoji": {
              "type": "string",
              "nullable": true
             },
             "is_internal_only": {
              "type": "boolean"
             },
             "owner_user_id": {
              "type": "integer",
              "nullable": true
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "archived_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "space_type": {
              "type": "string",
              "enum": [
               "shared",
               "personal"
              ]
             },
             "banner_image_id": {
              "type": "integer",
              "nullable": true
             },
             "article_count": {
              "type": "boolean"
             },
             "collection_count": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Spaces"
    ],
    "summary": "CREATE space - Shared spaces: global admin only - Personal spaces: any tenant user, limited to one per user",
    "operationId": "post-v1-app-kb-spaces",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "space": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing required fields: name, slug"
     },
     "403": {
      "description": "Only global admins can create shared spaces."
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "You already have a personal space."
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "description": {
          "type": "string"
         },
         "color_hex": {},
         "icon_emoji": {},
         "is_internal_only": {
          "type": "boolean"
         },
         "space_type": {
          "type": "string"
         }
        },
        "required": [
         "name",
         "slug"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/spaces/slug/{slug}": {
   "get": {
    "tags": [
     "Spaces"
    ],
    "summary": "By slug",
    "operationId": "get-v1-app-kb-spaces-slug-slug",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "slug",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "space": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this space"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/spaces/{space_id}": {
   "get": {
    "tags": [
     "Spaces"
    ],
    "summary": "Space (checks ACL)",
    "operationId": "get-v1-app-kb-spaces-space-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "space": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this space"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "tags": [
     "Spaces"
    ],
    "summary": "UPDATE space (need manage permission)",
    "operationId": "put-v1-app-kb-spaces-space-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "space": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No manage permission on space"
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "A space with that slug already exists in your organisation."
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "description": {
          "type": "string"
         },
         "color_hex": {},
         "icon_emoji": {},
         "is_internal_only": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Spaces"
    ],
    "summary": "Space (need manage permission)",
    "operationId": "delete-v1-app-kb-spaces-space-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No manage permission on space"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/spaces/{space_id}/collections": {
   "get": {
    "tags": [
     "Spaces"
    ],
    "summary": "Collections in a space (requires read on space)",
    "operationId": "get-v1-app-kb-spaces-space-id-collections",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collections": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "space_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "description": {
              "type": "string",
              "nullable": true
             },
             "sort_order": {
              "type": "integer"
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "archived_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "icon_emoji": {},
             "color_hex": {},
             "banner_image_id": {
              "type": "integer",
              "nullable": true
             },
             "logo_image_id": {
              "type": "integer",
              "nullable": true
             },
             "article_count": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this space"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Spaces"
    ],
    "summary": "CREATE collection in a space (need write/manage space)",
    "operationId": "post-v1-app-kb-spaces-space-id-collections",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collection": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing required fields: name, slug"
     },
     "403": {
      "description": "No write permission on space"
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "A collection with that slug already exists in your organisation."
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "description": {
          "type": "string"
         },
         "sort_order": {
          "type": "integer"
         },
         "icon_emoji": {},
         "color_hex": {}
        },
        "required": [
         "name",
         "slug"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/collections/slug/{slug}": {
   "get": {
    "tags": [
     "Collections"
    ],
    "summary": "By slug",
    "operationId": "get-v1-app-kb-collections-slug-slug",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "slug",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collection": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this collection"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/collections/{collection_id}": {
   "get": {
    "tags": [
     "Collections"
    ],
    "summary": "Collection (check ACL on collection)",
    "operationId": "get-v1-app-kb-collections-collection-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collection": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this collection"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "tags": [
     "Collections"
    ],
    "summary": "UPDATE collection (need manage on collection or space)",
    "operationId": "put-v1-app-kb-collections-collection-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collection": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No manage permission on collection"
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "A collection with that slug already exists in your organisation."
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "description": {
          "type": "string"
         },
         "sort_order": {
          "type": "integer"
         },
         "icon_emoji": {},
         "color_hex": {}
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Collections"
    ],
    "summary": "Collection",
    "operationId": "delete-v1-app-kb-collections-collection-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No manage permission on collection"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/collections/{collection_id}/articles": {
   "get": {
    "tags": [
     "Collections"
    ],
    "summary": "In a collection (read on space or collection)",
    "operationId": "get-v1-app-kb-collections-collection-id-articles",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "articles": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "space_id": {
              "type": "integer"
             },
             "collection_id": {
              "type": "integer",
              "nullable": true
             },
             "title": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "status": {
              "type": "string",
              "enum": [
               "draft",
               "published",
               "archived"
              ]
             },
             "review_interval_days": {
              "type": "integer",
              "nullable": true
             },
             "next_review_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "owner_user_id": {
              "type": "integer",
              "nullable": true
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "updated_by": {
              "type": "integer"
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "published_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "archived_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "view_count": {
              "type": "integer"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this collection"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Collections"
    ],
    "summary": "CREATE article in a collection (write on collection/space)",
    "operationId": "post-v1-app-kb-collections-collection-id-articles",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "article": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing required fields: title, slug"
     },
     "403": {
      "description": "No write permission in this collection"
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "An article with that title already exists in this collection."
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "status": {
          "type": "string"
         },
         "review_interval_days": {
          "type": "integer"
         },
         "owner_user_id": {
          "type": "integer"
         }
        },
        "required": [
         "title",
         "slug"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/articles/slug/{slug}": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "By slug",
    "operationId": "get-v1-app-kb-articles-slug-slug",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "slug",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "article": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/articles/{article_id}": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Article (ACL)",
    "operationId": "get-v1-app-kb-articles-article-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "article": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "put": {
    "tags": [
     "Articles"
    ],
    "summary": "UPDATE article metadata (write on article/collection/space)",
    "operationId": "put-v1-app-kb-articles-article-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "article": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No write permission on article"
     },
     "404": {
      "description": "User not found"
     },
     "409": {
      "description": "An article with that title already exists in this collection."
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "status": {
          "type": "string"
         },
         "review_interval_days": {
          "type": "integer"
         },
         "owner_user_id": {
          "type": "integer"
         },
         "space_id": {
          "type": "integer"
         },
         "collection_id": {
          "type": "integer"
         }
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Articles"
    ],
    "summary": "Article",
    "operationId": "delete-v1-app-kb-articles-article-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No permission to archive article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/articles/{article_id}/content": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Content (same read checks as article)",
    "operationId": "get-v1-app-kb-articles-article-id-content",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "version": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/articles/{article_id}/versions": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Versions (requires read)",
    "operationId": "get-v1-app-kb-articles-article-id-versions",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "versions": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "article_id": {
              "type": "integer"
             },
             "version_number": {
              "type": "integer"
             },
             "title": {
              "type": "string"
             },
             "content_markdown": {
              "type": "string"
             },
             "content_html": {
              "type": "string",
              "nullable": true
             },
             "content_search": {
              "type": "string",
              "nullable": true
             },
             "change_summary": {
              "type": "string",
              "nullable": true
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "is_current": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Articles"
    ],
    "summary": "CREATE new version (write)",
    "operationId": "post-v1-app-kb-articles-article-id-versions",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "version": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing required fields: title, content_markdown"
     },
     "403": {
      "description": "No write permission on article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string"
         },
         "content_markdown": {},
         "content_html": {},
         "change_summary": {}
        },
        "required": [
         "title",
         "content_markdown"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/articles/{article_id}/versions/{version_id}": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Version (read)",
    "operationId": "get-v1-app-kb-articles-article-id-versions-version-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "version_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "version": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "tags": [
     "Articles"
    ],
    "summary": "(write/manage)",
    "operationId": "delete-v1-app-kb-articles-article-id-versions-version-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "version_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No permission to delete version"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/tags": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Tags for tenant (any authenticated user)",
    "operationId": "get-v1-app-kb-tags",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "color_hex": {
              "type": "string",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Articles"
    ],
    "summary": "Create tag (Global Admin)",
    "operationId": "post-v1-app-kb-tags",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tag": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing required fields: name, slug"
     },
     "403": {
      "description": "Global admin required to manage tags"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "color_hex": {}
        },
        "required": [
         "name",
         "slug"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/tags/{tag_id}": {
   "put": {
    "tags": [
     "Articles"
    ],
    "summary": "Update tag (Global Admin)",
    "operationId": "put-v1-app-kb-tags-tag-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "tag_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tag": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required to manage tags"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string"
         },
         "slug": {
          "type": "string"
         },
         "color_hex": {}
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Articles"
    ],
    "summary": "(Global Admin)",
    "operationId": "delete-v1-app-kb-tags-tag-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "tag_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required to manage tags"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/articles/{article_id}/tags": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "For an article (requires read on article)",
    "operationId": "get-v1-app-kb-articles-article-id-tags",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "color_hex": {
              "type": "string",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Articles"
    ],
    "summary": "Set tags for an article (overwrite) – requires write on article",
    "operationId": "post-v1-app-kb-articles-article-id-tags",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "tags": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "color_hex": {
              "type": "string",
              "nullable": true
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "tag_ids must be an array of tag IDs"
     },
     "403": {
      "description": "No write permission on article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "tag_ids": {
          "type": "array",
          "items": {}
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/articles/{article_id}/comments": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "For article (requires read)",
    "operationId": "get-v1-app-kb-articles-article-id-comments",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "comments": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "article_id": {
              "type": "integer"
             },
             "parent_id": {
              "type": "integer",
              "nullable": true
             },
             "body": {
              "type": "string"
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "resolved_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Articles"
    ],
    "summary": "Create comment (requires read on article, usually fine for Reader+)",
    "operationId": "post-v1-app-kb-articles-article-id-comments",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "comment": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "Comment body is required"
     },
     "403": {
      "description": "No access to this article"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "body": {},
         "parent_id": {
          "type": "integer"
         }
        },
        "required": [
         "body"
        ]
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/comments/{comment_id}": {
   "put": {
    "tags": [
     "Articles"
    ],
    "summary": "Update comment (Global Admin or comment owner)",
    "operationId": "put-v1-app-kb-comments-comment-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "comment_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "comment": {}
         }
        }
       }
      }
     },
     "403": {
      "description": "No permission to edit comment"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "body": {},
         "resolved": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "Articles"
    ],
    "summary": "(Global Admin or owner)",
    "operationId": "delete-v1-app-kb-comments-comment-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "comment_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "No permission to delete comment"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/search": {
   "get": {
    "tags": [
     "Search & stats"
    ],
    "summary": "Search published articles",
    "operationId": "get-v1-app-kb-search",
    "description": "Search published articles. Each result passes the same read check as GET /articles/:id (article, collection or space), so titles from spaces someone can't open never show (KB's own search and Bramble search, #82).\n\nRequires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {}
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "results": {
           "type": "array",
           "items": {}
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Missing search query"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/stats": {
   "get": {
    "tags": [
     "Search & stats"
    ],
    "summary": "WiKi statistics",
    "operationId": "get-v1-app-kb-stats",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "spaces_count": {
           "type": "integer"
          },
          "articles_count": {
           "type": "integer"
          },
          "drafts_count": {
           "type": "integer"
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/articles/trending": {
   "get": {
    "tags": [
     "Articles"
    ],
    "summary": "Most recently updated articles (as \"trending\")",
    "operationId": "get-v1-app-kb-articles-trending",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "articles": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "title": {
              "type": "string"
             },
             "space_id": {
              "type": "integer"
             },
             "collection_id": {
              "type": "integer",
              "nullable": true
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "space_name": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/permissions": {
   "get": {
    "tags": [
     "Permissions"
    ],
    "summary": "List permissions",
    "operationId": "get-v1-app-kb-permissions",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "object_type",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "object_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "permissions": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "object_type": {
              "type": "string",
              "enum": [
               "space",
               "collection",
               "article"
              ]
             },
             "object_id": {
              "type": "integer"
             },
             "subject_type": {
              "type": "string",
              "enum": [
               "user",
               "group"
              ]
             },
             "subject_id": {
              "type": "integer"
             },
             "can_read": {
              "type": "boolean"
             },
             "can_write": {
              "type": "boolean"
             },
             "can_manage": {
              "type": "boolean"
             },
             "is_denied": {
              "type": "boolean"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "created_by": {
              "type": "integer"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "object_type and numeric object_id are required"
     },
     "403": {
      "description": "No manage permission on this object"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "tags": [
     "Permissions"
    ],
    "summary": "Create / update a permission entry POST /permissions body: { object_type, object_id, subject_type, subject_id, can_read, can_write, can_manage, is_denied }",
    "operationId": "post-v1-app-kb-permissions",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "permission": {}
         }
        }
       }
      }
     },
     "400": {
      "description": "object_type and numeric object_id are required"
     },
     "403": {
      "description": "No manage permission on this object"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "object_type": {
          "type": "string"
         },
         "object_id": {
          "type": "integer"
         },
         "subject_type": {
          "type": "string"
         },
         "subject_id": {
          "type": "integer"
         },
         "can_read": {
          "type": "boolean"
         },
         "can_write": {
          "type": "boolean"
         },
         "can_manage": {
          "type": "boolean"
         },
         "is_denied": {
          "type": "boolean"
         }
        }
       }
      }
     }
    }
   }
  },
  "/v1/app/kb/permissions/{perm_id}": {
   "delete": {
    "tags": [
     "Permissions"
    ],
    "summary": "Remove a permission",
    "operationId": "delete-v1-app-kb-permissions-perm-id",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "perm_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "Invalid permission id"
     },
     "403": {
      "description": "No manage permission on this object"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/subjects/users": {
   "get": {
    "tags": [
     "Permissions"
    ],
    "summary": "Find people (for permission pickers)",
    "operationId": "get-v1-app-kb-subjects-users",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {}
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "users": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "label": {
              "type": "string"
             },
             "email": {
              "type": "string",
              "nullable": true
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Unauthenticated"
     },
     "500": {
      "description": "Failed to load users"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/subjects/groups": {
   "get": {
    "tags": [
     "Permissions"
    ],
    "summary": "Find groups (for permission pickers)",
    "operationId": "get-v1-app-kb-subjects-groups",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {}
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "groups": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "label": {
              "type": "string"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "401": {
      "description": "Unauthenticated"
     },
     "500": {
      "description": "Failed to load groups"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/images": {
   "post": {
    "tags": [
     "Images"
    ],
    "summary": "Upload an image (multipart/form-data, field name: \"image\")",
    "operationId": "post-v1-app-kb-images",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "201": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "id": {
           "type": "integer"
          },
          "url": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "400": {
      "description": "No image file provided"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/spaces/{space_id}/banner": {
   "post": {
    "tags": [
     "Spaces"
    ],
    "summary": "Space banner",
    "operationId": "post-v1-app-kb-spaces-space-id-banner",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "tags": [
     "Spaces"
    ],
    "summary": "Remove a space's banner",
    "operationId": "delete-v1-app-kb-spaces-space-id-banner",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/collections/{collection_id}/banner": {
   "post": {
    "tags": [
     "Collections"
    ],
    "summary": "Collection banner",
    "operationId": "post-v1-app-kb-collections-collection-id-banner",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "tags": [
     "Collections"
    ],
    "summary": "Remove a collection's banner",
    "operationId": "delete-v1-app-kb-collections-collection-id-banner",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/collections/{collection_id}/logo": {
   "post": {
    "tags": [
     "Collections"
    ],
    "summary": "Collection logo",
    "operationId": "post-v1-app-kb-collections-collection-id-logo",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "tags": [
     "Collections"
    ],
    "summary": "Remove a collection's logo",
    "operationId": "delete-v1-app-kb-collections-collection-id-logo",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/collections": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Collections across all spaces (admin only)",
    "operationId": "get-v1-app-kb-admin-collections",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "collections": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "tenant_id": {
              "type": "integer"
             },
             "space_id": {
              "type": "integer"
             },
             "name": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "description": {
              "type": "string",
              "nullable": true
             },
             "sort_order": {
              "type": "integer"
             },
             "created_by": {
              "type": "integer"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "archived_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "icon_emoji": {
              "type": "string"
             },
             "color_hex": {
              "type": "string"
             },
             "banner_image_id": {
              "type": "integer",
              "nullable": true
             },
             "logo_image_id": {
              "type": "integer",
              "nullable": true
             },
             "space_name": {
              "type": "string"
             },
             "space_slug": {
              "type": "string"
             },
             "space_color": {
              "type": "string",
              "nullable": true
             },
             "space_icon": {
              "type": "string",
              "nullable": true
             },
             "space_type": {
              "type": "string",
              "enum": [
               "shared",
               "personal"
              ]
             },
             "article_count": {
              "type": "boolean"
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/articles": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Articles across all spaces (admin only), filterable by status",
    "operationId": "get-v1-app-kb-admin-articles",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "articles": {
           "type": "array",
           "items": {
            "type": "object",
            "properties": {
             "id": {
              "type": "integer"
             },
             "title": {
              "type": "string"
             },
             "slug": {
              "type": "string"
             },
             "status": {
              "type": "string",
              "enum": [
               "draft",
               "published",
               "archived"
              ]
             },
             "updated_at": {
              "type": "string",
              "format": "date-time"
             },
             "created_at": {
              "type": "string",
              "format": "date-time"
             },
             "archived_at": {
              "type": "string",
              "format": "date-time",
              "nullable": true
             },
             "collection_name": {
              "type": "string"
             },
             "collection_slug": {
              "type": "string"
             },
             "space_name": {
              "type": "string"
             },
             "space_slug": {
              "type": "string"
             },
             "space_color": {
              "type": "string",
              "nullable": true
             },
             "space_type": {
              "type": "string",
              "enum": [
               "shared",
               "personal"
              ]
             }
            }
           }
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/archived": {
   "get": {
    "tags": [
     "Admin"
    ],
    "summary": "Archived items for the tenant (global admin only)",
    "operationId": "get-v1-app-kb-admin-archived",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "spaces": {
           "type": "array",
           "items": {}
          },
          "collections": {
           "type": "array",
           "items": {}
          },
          "articles": {
           "type": "array",
           "items": {}
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/spaces/{space_id}/restore": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "RESTORE archived space",
    "operationId": "post-v1-app-kb-admin-spaces-space-id-restore",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          },
          "slug": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/spaces/{space_id}/purge": {
   "delete": {
    "tags": [
     "Admin"
    ],
    "summary": "PERMANENTLY delete archived space",
    "operationId": "delete-v1-app-kb-admin-spaces-space-id-purge",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "space_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/collections/{collection_id}/restore": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "RESTORE archived collection",
    "operationId": "post-v1-app-kb-admin-collections-collection-id-restore",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          },
          "slug": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/collections/{collection_id}/purge": {
   "delete": {
    "tags": [
     "Admin"
    ],
    "summary": "PERMANENTLY delete archived collection",
    "operationId": "delete-v1-app-kb-admin-collections-collection-id-purge",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "collection_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/articles/{article_id}/restore": {
   "post": {
    "tags": [
     "Admin"
    ],
    "summary": "RESTORE archived article",
    "operationId": "post-v1-app-kb-admin-articles-article-id-restore",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  },
  "/v1/app/kb/admin/articles/{article_id}/purge": {
   "delete": {
    "tags": [
     "Admin"
    ],
    "summary": "PERMANENTLY delete archived article",
    "operationId": "delete-v1-app-kb-admin-articles-article-id-purge",
    "description": "Requires: Signed-in session, `X-API-Key`, or a Bramble app access token (`Authorization: Bearer`). Licence: WiKi.",
    "parameters": [
     {
      "name": "article_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "message": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "403": {
      "description": "Global admin required"
     },
     "404": {
      "description": "User not found"
     },
     "500": {
      "description": "Internal Server Error"
     }
    },
    "security": [
     {
      "apiKey": []
     },
     {
      "session": []
     },
     {
      "bearer": []
     }
    ]
   }
  }
 }
}