diff --git a/appinfo/console.php b/appinfo/console.php
new file mode 100644
index 0000000..f645afd
--- /dev/null
+++ b/appinfo/console.php
@@ -0,0 +1,11 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use OCA\Forum\Command\TestNotifier;
+
+/** @var Symfony\Component\Console\Application $application */
+$application->add(\OC::$server->get(TestNotifier::class));
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 53c31d2..b523b99 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -55,6 +55,9 @@ The forum integrates seamlessly with your Nextcloud instance, using your existin
+
+ OCA\Forum\Command\TestNotifier
+
Forum
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 47a3c17..c26b57f 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -6,6 +6,7 @@ namespace OCA\Forum\AppInfo;
use OCA\Forum\Listener\UserEventListener;
use OCA\Forum\Middleware\PermissionMiddleware;
+use OCA\Forum\Notification\Notifier;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
@@ -33,6 +34,9 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(UserCreatedEvent::class, UserEventListener::class);
$context->registerEventListener(UserDeletedEvent::class, UserEventListener::class);
$context->registerEventListener(UserChangedEvent::class, UserEventListener::class);
+
+ // Register notification notifier
+ $context->registerNotifierService(Notifier::class);
}
public function boot(IBootContext $context): void {
diff --git a/lib/Command/TestNotifier.php b/lib/Command/TestNotifier.php
new file mode 100644
index 0000000..e9d5dbf
--- /dev/null
+++ b/lib/Command/TestNotifier.php
@@ -0,0 +1,81 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Command;
+
+use OCA\Forum\Notification\Notifier;
+use OCP\L10N\IFactory;
+use OCP\Notification\IManager as INotificationManager;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class TestNotifier extends Command {
+ public function __construct(
+ private INotificationManager $notificationManager,
+ private IFactory $l10nFactory,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ parent::configure();
+ $this->setName('forum:test-notifier')
+ ->setDescription('Test the forum notification system');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ try {
+ $output->writeln('Testing Forum Notifier...');
+
+ // Instantiate the notifier
+ $notifier = new Notifier($this->l10nFactory);
+
+ $output->writeln('✓ Notifier instantiated successfully');
+ $output->writeln(' ID: ' . $notifier->getID());
+ $output->writeln(' Name: ' . $notifier->getName());
+
+ // Create a test notification (matching production structure)
+ $notification = $this->notificationManager->createNotification();
+
+ $notification->setApp('forum')
+ ->setUser('admin')
+ ->setDateTime(new \DateTime())
+ ->setObject('thread', '1')
+ ->setSubject('new_posts', [
+ 'threadId' => 1,
+ 'threadTitle' => 'Test Thread',
+ 'threadSlug' => 'test-thread',
+ 'lastPostId' => 1,
+ 'postCount' => 1,
+ ])
+ ->setLink('http://localhost/apps/forum/t/test-thread')
+ ->setIcon('http://localhost/apps/forum/img/app-dark.svg');
+
+ $output->writeln('✓ Test notification created');
+
+ // Try to prepare it
+ $prepared = $notifier->prepare($notification, 'en');
+
+ $output->writeln('✓ Notification prepared successfully');
+ $output->writeln(' Subject: ' . $prepared->getParsedSubject());
+ $output->writeln(' Link: ' . $prepared->getLink());
+ $output->writeln(' Icon: ' . $prepared->getIcon());
+
+ $output->writeln('');
+ $output->writeln('All tests passed! The notifier is working correctly.');
+
+ return 0;
+ } catch (\Exception $e) {
+ $output->writeln('✗ Error: ' . $e->getMessage() . '');
+ $output->writeln('Trace:');
+ $output->writeln($e->getTraceAsString());
+
+ return 1;
+ }
+ }
+}
diff --git a/lib/Controller/PostController.php b/lib/Controller/PostController.php
index 906b571..f6e8f0d 100644
--- a/lib/Controller/PostController.php
+++ b/lib/Controller/PostController.php
@@ -17,6 +17,7 @@ use OCA\Forum\Db\ReadMarkerMapper;
use OCA\Forum\Db\ThreadMapper;
use OCA\Forum\Db\UserStatsMapper;
use OCA\Forum\Service\BBCodeService;
+use OCA\Forum\Service\NotificationService;
use OCA\Forum\Service\PermissionService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
@@ -41,6 +42,7 @@ class PostController extends OCSController {
private BBCodeMapper $bbCodeMapper,
private PermissionService $permissionService,
private ReadMarkerMapper $readMarkerMapper,
+ private NotificationService $notificationService,
private IUserSession $userSession,
private LoggerInterface $logger,
) {
@@ -268,6 +270,14 @@ class PostController extends OCSController {
// Don't fail the request if category update fails
}
+ // Notify registered users about the new post
+ try {
+ $this->notificationService->notifyThreadSubscribers($threadId, $createdPost->getId(), $user->getUID());
+ } catch (\Exception $e) {
+ $this->logger->warning('Failed to send notifications for new post: ' . $e->getMessage());
+ // Don't fail the request if notification sending fails
+ }
+
return new DataResponse(Post::enrichPostContent($createdPost), Http::STATUS_CREATED);
} catch (\Exception $e) {
$this->logger->error('Error creating post: ' . $e->getMessage());
diff --git a/lib/Controller/ReadMarkerController.php b/lib/Controller/ReadMarkerController.php
index 621561c..0749ab6 100644
--- a/lib/Controller/ReadMarkerController.php
+++ b/lib/Controller/ReadMarkerController.php
@@ -8,6 +8,7 @@ declare(strict_types=1);
namespace OCA\Forum\Controller;
use OCA\Forum\Db\ReadMarkerMapper;
+use OCA\Forum\Service\NotificationService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
@@ -23,6 +24,7 @@ class ReadMarkerController extends OCSController {
string $appName,
IRequest $request,
private ReadMarkerMapper $readMarkerMapper,
+ private NotificationService $notificationService,
private IUserSession $userSession,
private LoggerInterface $logger,
) {
@@ -136,6 +138,18 @@ class ReadMarkerController extends OCSController {
$lastReadPostId
);
+ // Dismiss notifications if the user has caught up with the thread
+ try {
+ $this->notificationService->dismissNotificationsIfRead(
+ $user->getUID(),
+ $threadId,
+ $lastReadPostId
+ );
+ } catch (\Exception $e) {
+ $this->logger->warning('Failed to dismiss notifications: ' . $e->getMessage());
+ // Don't fail the request if notification dismissal fails
+ }
+
return new DataResponse($marker->jsonSerialize());
} catch (\Exception $e) {
$this->logger->error('Error marking thread as read: ' . $e->getMessage());
diff --git a/lib/Controller/ThreadController.php b/lib/Controller/ThreadController.php
index a02d8ef..6faa960 100644
--- a/lib/Controller/ThreadController.php
+++ b/lib/Controller/ThreadController.php
@@ -13,6 +13,7 @@ use OCA\Forum\Db\Post;
use OCA\Forum\Db\PostMapper;
use OCA\Forum\Db\Thread;
use OCA\Forum\Db\ThreadMapper;
+use OCA\Forum\Db\ThreadSubscriptionMapper;
use OCA\Forum\Db\UserStatsMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
@@ -32,6 +33,7 @@ class ThreadController extends OCSController {
private CategoryMapper $categoryMapper,
private PostMapper $postMapper,
private UserStatsMapper $userStatsMapper,
+ private ThreadSubscriptionMapper $threadSubscriptionMapper,
private IUserSession $userSession,
private LoggerInterface $logger,
) {
@@ -244,6 +246,13 @@ class ThreadController extends OCSController {
$this->logger->warning('Failed to update user stats: ' . $e->getMessage());
}
+ // Auto-subscribe the thread creator to receive notifications
+ try {
+ $this->threadSubscriptionMapper->subscribe($user->getUID(), $createdThread->getId());
+ } catch (\Exception $e) {
+ $this->logger->warning('Failed to subscribe thread creator: ' . $e->getMessage());
+ }
+
return new DataResponse($createdThread->jsonSerialize(), Http::STATUS_CREATED);
} catch (\Exception $e) {
$this->logger->error('Error creating thread: ' . $e->getMessage());
diff --git a/lib/Controller/ThreadSubscriptionController.php b/lib/Controller/ThreadSubscriptionController.php
new file mode 100644
index 0000000..d29b7e9
--- /dev/null
+++ b/lib/Controller/ThreadSubscriptionController.php
@@ -0,0 +1,132 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Controller;
+
+use OCA\Forum\Db\ThreadSubscriptionMapper;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\ApiRoute;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\OCSController;
+use OCP\IRequest;
+use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
+
+class ThreadSubscriptionController extends OCSController {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private ThreadSubscriptionMapper $subscriptionMapper,
+ private IUserSession $userSession,
+ private LoggerInterface $logger,
+ ) {
+ parent::__construct($appName, $request);
+ }
+
+ /**
+ * Subscribe current user to a thread to receive notifications
+ *
+ * @param int $threadId Thread ID
+ * @return DataResponse, array{}>
+ *
+ * 200: User subscribed to thread
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/api/threads/{threadId}/subscribe')]
+ public function subscribe(int $threadId): DataResponse {
+ try {
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ return new DataResponse(['error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED);
+ }
+
+ $subscription = $this->subscriptionMapper->subscribe($user->getUID(), $threadId);
+ return new DataResponse([
+ 'success' => true,
+ 'subscription' => $subscription->jsonSerialize(),
+ ]);
+ } catch (\Exception $e) {
+ $this->logger->error('Error subscribing user to thread: ' . $e->getMessage());
+ return new DataResponse(['error' => 'Failed to subscribe to thread'], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Unsubscribe current user from a thread
+ *
+ * @param int $threadId Thread ID
+ * @return DataResponse, array{}>
+ *
+ * 200: User unsubscribed from thread
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'DELETE', url: '/api/threads/{threadId}/subscribe')]
+ public function unsubscribe(int $threadId): DataResponse {
+ try {
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ return new DataResponse(['error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED);
+ }
+
+ $this->subscriptionMapper->unsubscribe($user->getUID(), $threadId);
+ return new DataResponse(['success' => true]);
+ } catch (\Exception $e) {
+ $this->logger->error('Error unsubscribing user from thread: ' . $e->getMessage());
+ return new DataResponse(['error' => 'Failed to unsubscribe from thread'], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Check if current user is subscribed to a thread
+ *
+ * @param int $threadId Thread ID
+ * @return DataResponse, array{}>
+ *
+ * 200: Subscription status returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/threads/{threadId}/subscribe')]
+ public function isSubscribed(int $threadId): DataResponse {
+ try {
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ return new DataResponse(['error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED);
+ }
+
+ $isSubscribed = $this->subscriptionMapper->isUserSubscribed($user->getUID(), $threadId);
+ return new DataResponse(['isSubscribed' => $isSubscribed]);
+ } catch (\Exception $e) {
+ $this->logger->error('Error checking thread subscription status: ' . $e->getMessage());
+ return new DataResponse(['error' => 'Failed to check subscription status'], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Get all threads the current user is subscribed to
+ *
+ * @return DataResponse>, array{}>
+ *
+ * 200: Thread subscriptions returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/thread-subscriptions')]
+ public function getUserSubscriptions(): DataResponse {
+ try {
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ return new DataResponse(['error' => 'User not authenticated'], Http::STATUS_UNAUTHORIZED);
+ }
+
+ $subscriptions = $this->subscriptionMapper->findByUserId($user->getUID());
+ return new DataResponse(array_map(fn ($r) => $r->jsonSerialize(), $subscriptions));
+ } catch (\Exception $e) {
+ $this->logger->error('Error fetching user thread subscriptions: ' . $e->getMessage());
+ return new DataResponse(['error' => 'Failed to fetch thread subscriptions'], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+}
diff --git a/lib/Db/PostMapper.php b/lib/Db/PostMapper.php
index 3bc2fd5..6aa7f2a 100644
--- a/lib/Db/PostMapper.php
+++ b/lib/Db/PostMapper.php
@@ -156,6 +156,30 @@ class PostMapper extends QBMapper {
return (int)($row['count'] ?? 0);
}
+ /**
+ * Count unread posts in a thread after a specific post ID
+ *
+ * @param int $threadId Thread ID
+ * @param int $afterPostId Post ID to count after (0 to count all posts)
+ * @return int Number of posts after the given post ID
+ */
+ public function countUnreadInThread(int $threadId, int $afterPostId = 0): int {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select($qb->func()->count('*', 'count'))
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('thread_id', $qb->createNamedParameter($threadId, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->isNull('deleted_at'));
+
+ if ($afterPostId > 0) {
+ $qb->andWhere($qb->expr()->gt('id', $qb->createNamedParameter($afterPostId, IQueryBuilder::PARAM_INT)));
+ }
+
+ $result = $qb->executeQuery();
+ $row = $result->fetch();
+ $result->closeCursor();
+ return (int)($row['count'] ?? 0);
+ }
+
/**
* Search posts by content (replies only, excluding first posts)
*
diff --git a/lib/Db/Thread.php b/lib/Db/Thread.php
index b413d01..4651e69 100644
--- a/lib/Db/Thread.php
+++ b/lib/Db/Thread.php
@@ -114,6 +114,21 @@ class Thread extends Entity implements JsonSerializable {
$thread['categoryName'] = null;
}
+ // Add subscription status for the current user
+ try {
+ $userSession = \OC::$server->get(\OCP\IUserSession::class);
+ $user = $userSession->getUser();
+ if ($user) {
+ $subscriptionMapper = \OC::$server->get(\OCA\Forum\Db\ThreadSubscriptionMapper::class);
+ $thread['isSubscribed'] = $subscriptionMapper->isUserSubscribed($user->getUID(), $thread['id']);
+ } else {
+ $thread['isSubscribed'] = false;
+ }
+ } catch (\Exception $e) {
+ // If there's an error checking subscription, default to false
+ $thread['isSubscribed'] = false;
+ }
+
return $thread;
}
}
diff --git a/lib/Db/ThreadSubscription.php b/lib/Db/ThreadSubscription.php
new file mode 100644
index 0000000..b615db0
--- /dev/null
+++ b/lib/Db/ThreadSubscription.php
@@ -0,0 +1,44 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Db;
+
+use JsonSerializable;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * @method int getId()
+ * @method void setId(int $value)
+ * @method string getUserId()
+ * @method void setUserId(string $value)
+ * @method int getThreadId()
+ * @method void setThreadId(int $value)
+ * @method int getCreatedAt()
+ * @method void setCreatedAt(int $value)
+ */
+class ThreadSubscription extends Entity implements JsonSerializable {
+ protected $userId;
+ protected $threadId;
+ protected $createdAt;
+
+ public function __construct() {
+ $this->addType('id', 'integer');
+ $this->addType('userId', 'string');
+ $this->addType('threadId', 'integer');
+ $this->addType('createdAt', 'integer');
+ }
+
+ public function jsonSerialize(): array {
+ return [
+ 'id' => $this->getId(),
+ 'userId' => $this->getUserId(),
+ 'threadId' => $this->getThreadId(),
+ 'createdAt' => $this->getCreatedAt(),
+ ];
+ }
+}
diff --git a/lib/Db/ThreadSubscriptionMapper.php b/lib/Db/ThreadSubscriptionMapper.php
new file mode 100644
index 0000000..35cfda5
--- /dev/null
+++ b/lib/Db/ThreadSubscriptionMapper.php
@@ -0,0 +1,142 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Db;
+
+use OCA\Forum\AppInfo\Application;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * @template-extends QBMapper
+ */
+class ThreadSubscriptionMapper extends QBMapper {
+ public function __construct(
+ IDBConnection $db,
+ ) {
+ parent::__construct($db, Application::tableName('forum_thread_subs'), ThreadSubscription::class);
+ }
+
+ /**
+ * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
+ * @throws DoesNotExistException
+ */
+ public function find(int $id): ThreadSubscription {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()
+ ->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))
+ );
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
+ * @throws DoesNotExistException
+ */
+ public function findByUserAndThread(string $userId, int $threadId): ThreadSubscription {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
+ )
+ ->andWhere(
+ $qb->expr()->eq('thread_id', $qb->createNamedParameter($threadId, IQueryBuilder::PARAM_INT))
+ );
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * Check if a user is subscribed to a thread
+ */
+ public function isUserSubscribed(string $userId, int $threadId): bool {
+ try {
+ $this->findByUserAndThread($userId, $threadId);
+ return true;
+ } catch (DoesNotExistException $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get all subscribed users for a thread
+ *
+ * @return array
+ */
+ public function findByThread(int $threadId): array {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()->eq('thread_id', $qb->createNamedParameter($threadId, IQueryBuilder::PARAM_INT))
+ );
+ return $this->findEntities($qb);
+ }
+
+ /**
+ * Get all thread subscriptions for a user
+ *
+ * @return array
+ */
+ public function findByUserId(string $userId): array {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
+ );
+ return $this->findEntities($qb);
+ }
+
+ /**
+ * Subscribe a user to a thread
+ */
+ public function subscribe(string $userId, int $threadId): ThreadSubscription {
+ // Check if already subscribed
+ if ($this->isUserSubscribed($userId, $threadId)) {
+ return $this->findByUserAndThread($userId, $threadId);
+ }
+
+ // Create new subscription
+ $subscription = new ThreadSubscription();
+ $subscription->setUserId($userId);
+ $subscription->setThreadId($threadId);
+ $subscription->setCreatedAt(time());
+ return $this->insert($subscription);
+ }
+
+ /**
+ * Unsubscribe a user from a thread
+ */
+ public function unsubscribe(string $userId, int $threadId): void {
+ try {
+ $subscription = $this->findByUserAndThread($userId, $threadId);
+ $this->delete($subscription);
+ } catch (DoesNotExistException $e) {
+ // Already not subscribed, nothing to do
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function findAll(): array {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')->from($this->getTableName());
+ return $this->findEntities($qb);
+ }
+}
diff --git a/lib/Migration/Version2Date20251114222614.php b/lib/Migration/Version2Date20251114222614.php
new file mode 100644
index 0000000..6b6d0ca
--- /dev/null
+++ b/lib/Migration/Version2Date20251114222614.php
@@ -0,0 +1,75 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+class Version2Date20251114222614 extends SimpleMigrationStep {
+ /**
+ * @param IOutput $output
+ * @param Closure(): ISchemaWrapper $schemaClosure
+ * @param array $options
+ */
+ public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
+ }
+
+ /**
+ * @param IOutput $output
+ * @param Closure(): ISchemaWrapper $schemaClosure
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ $this->createForumThreadSubsTable($schema);
+
+ return $schema;
+ }
+
+ private function createForumThreadSubsTable(ISchemaWrapper $schema): void {
+ if ($schema->hasTable('forum_thread_subs')) {
+ return;
+ }
+
+ $table = $schema->createTable('forum_thread_subs');
+ $table->addColumn('id', 'bigint', [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ 'unsigned' => true,
+ ]);
+ $table->addColumn('user_id', 'string', [
+ 'notnull' => true,
+ 'length' => 64,
+ ]);
+ $table->addColumn('thread_id', 'bigint', [
+ 'notnull' => true,
+ 'unsigned' => true,
+ ]);
+ $table->addColumn('created_at', 'integer', [
+ 'notnull' => true,
+ 'unsigned' => true,
+ ]);
+ $table->setPrimaryKey(['id']);
+ $table->addIndex(['user_id'], 'thread_subs_uid_idx');
+ $table->addIndex(['thread_id'], 'thread_subs_tid_idx');
+ $table->addUniqueIndex(['user_id', 'thread_id'], 'thread_subs_uniq_idx');
+ }
+
+ /**
+ * @param IOutput $output
+ * @param Closure(): ISchemaWrapper $schemaClosure
+ * @param array $options
+ */
+ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
+ }
+}
diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php
new file mode 100644
index 0000000..60b8e36
--- /dev/null
+++ b/lib/Notification/Notifier.php
@@ -0,0 +1,112 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Notification;
+
+use OCA\Forum\AppInfo\Application;
+use OCP\L10N\IFactory;
+use OCP\Notification\INotification;
+use OCP\Notification\INotifier;
+use OCP\Notification\UnknownNotificationException;
+
+class Notifier implements INotifier {
+ public function __construct(
+ private IFactory $l10nFactory,
+ ) {
+ }
+
+ /**
+ * Identifier of the notifier, only use [a-z0-9_]
+ */
+ public function getID(): string {
+ return Application::APP_ID;
+ }
+
+ /**
+ * Human-readable name describing the notifier
+ */
+ public function getName(): string {
+ return $this->l10nFactory->get(Application::APP_ID)->t('Forum');
+ }
+
+ /**
+ * Prepare the notification for display
+ *
+ * @param INotification $notification
+ * @param string $languageCode The code of the language that should be used to prepare the notification
+ * @return INotification
+ * @throws \InvalidArgumentException When the notification was not prepared by this app or is not of the expected type
+ */
+ public function prepare(INotification $notification, string $languageCode): INotification {
+ if ($notification->getApp() !== Application::APP_ID) {
+ throw new UnknownNotificationException();
+ }
+
+ $l = $this->l10nFactory->get(Application::APP_ID, $languageCode);
+
+ switch ($notification->getSubject()) {
+ case 'new_posts':
+ $parameters = $notification->getSubjectParameters();
+ $threadId = $parameters['threadId'] ?? 0;
+ $threadTitle = $parameters['threadTitle'] ?? 'Unknown Thread';
+ $postCount = $parameters['postCount'] ?? 1;
+
+ // Set the rich subject with thread title
+ $notification->setRichSubject(
+ $l->n(
+ 'New reply in {thread}',
+ '{count} new replies in {thread}',
+ $postCount
+ ),
+ [
+ 'thread' => [
+ 'type' => 'highlight',
+ 'id' => (string)$threadId,
+ 'name' => $threadTitle,
+ ],
+ 'count' => [
+ 'type' => 'highlight',
+ 'id' => (string)$postCount,
+ 'name' => (string)$postCount,
+ ],
+ ]
+ );
+
+ // Set the parsed subject from rich subject
+ $this->setParsedSubjectFromRichSubject($notification);
+
+ return $notification;
+
+ default:
+ throw new UnknownNotificationException();
+ }
+ }
+
+ /**
+ * Helper function to set the parsed subject from the rich subject
+ * This extracts the parameter names from rich subject placeholders
+ *
+ * @param INotification $notification
+ */
+ protected function setParsedSubjectFromRichSubject(INotification $notification): void {
+ $placeholders = $replacements = [];
+ $richParams = $notification->getRichSubjectParameters();
+ $richSubject = $notification->getRichSubject();
+
+ foreach ($richParams as $placeholder => $parameter) {
+ $placeholders[] = '{' . $placeholder . '}';
+ if (isset($parameter['type']) && $parameter['type'] === 'file') {
+ $replacements[] = $parameter['path'] ?? $parameter['name'] ?? '';
+ } else {
+ $replacements[] = $parameter['name'] ?? '';
+ }
+ }
+
+ $parsedSubject = str_replace($placeholders, $replacements, $richSubject);
+ $notification->setParsedSubject($parsedSubject);
+ }
+}
diff --git a/lib/Service/NotificationService.php b/lib/Service/NotificationService.php
new file mode 100644
index 0000000..fff0fa5
--- /dev/null
+++ b/lib/Service/NotificationService.php
@@ -0,0 +1,155 @@
+
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace OCA\Forum\Service;
+
+use OCA\Forum\Db\PostMapper;
+use OCA\Forum\Db\ReadMarkerMapper;
+use OCA\Forum\Db\ThreadMapper;
+use OCA\Forum\Db\ThreadSubscriptionMapper;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\IURLGenerator;
+use OCP\Notification\IManager as INotificationManager;
+use Psr\Log\LoggerInterface;
+
+class NotificationService {
+ public function __construct(
+ private INotificationManager $notificationManager,
+ private ThreadSubscriptionMapper $subscriptionMapper,
+ private ThreadMapper $threadMapper,
+ private PostMapper $postMapper,
+ private ReadMarkerMapper $readMarkerMapper,
+ private IURLGenerator $urlGenerator,
+ private LoggerInterface $logger,
+ ) {
+ }
+
+ /**
+ * Notify subscribed users when a new post is added to a thread
+ */
+ public function notifyThreadSubscribers(int $threadId, int $postId, string $authorId): void {
+ // Get all subscribed users for this thread
+ $subscriptions = $this->subscriptionMapper->findByThread($threadId);
+
+ // Get thread information
+ try {
+ $thread = $this->threadMapper->find($threadId);
+ } catch (\Exception $e) {
+ $this->logger->warning('Thread not found for notifications', [
+ 'threadId' => $threadId,
+ 'error' => $e->getMessage(),
+ ]);
+ return;
+ }
+
+ foreach ($subscriptions as $subscription) {
+ $userId = $subscription->getUserId();
+
+ // Don't notify the author of the post
+ if ($userId === $authorId) {
+ continue;
+ }
+
+ // Create or update notification (collating multiple posts)
+ $this->createOrUpdateNotification($userId, $threadId, $postId, $thread->getTitle(), $thread->getSlug());
+ }
+ }
+
+ /**
+ * Create or update a notification for a user about a thread
+ * This allows collating multiple posts into a single notification
+ */
+ private function createOrUpdateNotification(string $userId, int $threadId, int $postId, string $threadTitle, string $threadSlug): void {
+ // Calculate the number of unread posts
+ $postCount = $this->getUnreadPostCount($userId, $threadId, $postId);
+
+ // Mark existing notifications for this thread/user as processed (to update them)
+ $existingNotification = $this->notificationManager->createNotification();
+ $existingNotification->setApp('forum')
+ ->setUser($userId)
+ ->setObject('thread', (string)$threadId)
+ ->setSubject('new_posts');
+ $this->notificationManager->markProcessed($existingNotification);
+
+ // Create new notification with updated post count
+ $notification = $this->notificationManager->createNotification();
+
+ // Generate the thread link and icon
+ $threadLink = $this->urlGenerator->linkToRouteAbsolute('forum.page.index') . 't/' . $threadSlug;
+ $iconPath = $this->urlGenerator->imagePath('forum', 'app-dark.svg');
+ $iconUrl = $this->urlGenerator->getAbsoluteURL($iconPath);
+
+ $notification->setApp('forum')
+ ->setUser($userId)
+ ->setDateTime(new \DateTime())
+ ->setObject('thread', (string)$threadId)
+ ->setSubject('new_posts', [
+ 'threadId' => $threadId,
+ 'threadTitle' => $threadTitle,
+ 'threadSlug' => $threadSlug,
+ 'lastPostId' => $postId,
+ 'postCount' => $postCount,
+ ])
+ ->setLink($threadLink)
+ ->setIcon($iconUrl);
+
+ $this->notificationManager->notify($notification);
+ }
+
+ /**
+ * Get the count of unread posts for a user in a thread
+ * Uses an efficient DB COUNT query instead of fetching all posts
+ */
+ private function getUnreadPostCount(string $userId, int $threadId, int $latestPostId): int {
+ try {
+ // Get the user's read marker for this thread
+ $readMarker = $this->readMarkerMapper->findByUserAndThread($userId, $threadId);
+ $lastReadPostId = $readMarker->getLastReadPostId();
+
+ // Count posts after the last read post using DB query
+ $unreadCount = $this->postMapper->countUnreadInThread($threadId, $lastReadPostId);
+
+ return max(1, $unreadCount); // At least 1 (the current post)
+ } catch (DoesNotExistException $e) {
+ // No read marker, count all posts in the thread
+ $count = $this->postMapper->countUnreadInThread($threadId, 0);
+
+ return max(1, $count); // At least 1
+ }
+ }
+
+ /**
+ * Dismiss notifications for a user when they view a thread
+ */
+ public function dismissThreadNotifications(string $userId, int $threadId): void {
+ $notification = $this->notificationManager->createNotification();
+ $notification->setApp('forum')
+ ->setUser($userId)
+ ->setObject('thread', (string)$threadId);
+
+ $this->notificationManager->markProcessed($notification);
+ }
+
+ /**
+ * Dismiss notifications when read marker catches up
+ */
+ public function dismissNotificationsIfRead(string $userId, int $threadId, int $lastReadPostId): void {
+ // Get the thread to check the last post
+ try {
+ $thread = $this->threadMapper->find($threadId);
+ $lastPostId = $thread->getLastPostId();
+
+ // If user has read up to or past the last post, dismiss notifications
+ if ($lastPostId && $lastReadPostId >= $lastPostId) {
+ $this->dismissThreadNotifications($userId, $threadId);
+ }
+ } catch (\Exception $e) {
+ // Thread not found or error, just dismiss anyway
+ $this->dismissThreadNotifications($userId, $threadId);
+ }
+ }
+}
diff --git a/openapi.json b/openapi.json
index 4470eeb..f4d338b 100644
--- a/openapi.json
+++ b/openapi.json
@@ -1,8245 +1,7619 @@
{
- "openapi": "3.0.3",
- "info": {
- "title": "forum",
- "version": "0.0.1",
- "description": "A community-driven forum built right into your Nextcloud instance",
- "license": {
- "name": "agpl"
- }
+ "openapi": "3.0.3",
+ "info": {
+ "title": "forum",
+ "version": "0.0.1",
+ "description": "A community-driven forum built right into your Nextcloud instance",
+ "license": {
+ "name": "agpl"
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "basic_auth": {
+ "type": "http",
+ "scheme": "basic"
+ },
+ "bearer_auth": {
+ "type": "http",
+ "scheme": "bearer"
+ }
},
- "components": {
- "securitySchemes": {
- "basic_auth": {
- "type": "http",
- "scheme": "basic"
- },
- "bearer_auth": {
- "type": "http",
- "scheme": "bearer"
+ "schemas": {
+ "OCSMeta": {
+ "type": "object",
+ "required": ["status", "statuscode"],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "statuscode": {
+ "type": "integer"
+ },
+ "message": {
+ "type": "string"
+ },
+ "totalitems": {
+ "type": "string"
+ },
+ "itemsperpage": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "paths": {
+ "/ocs/v2.php/apps/forum/api/admin/dashboard": {
+ "get": {
+ "operationId": "admin-dashboard",
+ "summary": "Get dashboard statistics",
+ "tags": ["admin"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
}
- },
- "schemas": {
- "OCSMeta": {
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Dashboard stats returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/admin/users": {
+ "get": {
+ "operationId": "admin-users",
+ "summary": "Get all forum users with their roles",
+ "tags": ["admin"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Users list returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["users"],
+ "properties": {
+ "users": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/admin/settings": {
+ "get": {
+ "operationId": "admin-get-settings",
+ "summary": "Get general forum settings",
+ "tags": ["admin"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Settings returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "admin-update-settings",
+ "summary": "Update general forum settings",
+ "tags": ["admin"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
"type": "object",
- "required": [
- "status",
- "statuscode"
- ],
"properties": {
- "status": {
- "type": "string"
- },
- "statuscode": {
- "type": "integer"
- },
- "message": {
- "type": "string"
- },
- "totalitems": {
- "type": "string"
- },
- "itemsperpage": {
- "type": "string"
- }
+ "title": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Forum title"
+ },
+ "subtitle": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Forum subtitle"
+ }
}
+ }
}
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Settings updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
+ }
},
- "paths": {
- "/ocs/v2.php/apps/forum/api/admin/dashboard": {
- "get": {
- "operationId": "admin-dashboard",
- "summary": "Get dashboard statistics",
- "tags": [
- "admin"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Dashboard stats returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
+ "/ocs/v2.php/apps/forum/api/bbcodes": {
+ "get": {
+ "operationId": "bb_code-index",
+ "summary": "Get all BBCodes (excludes builtin codes)",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
}
- },
- "/ocs/v2.php/apps/forum/api/admin/users": {
- "get": {
- "operationId": "admin-users",
- "summary": "Get all forum users with their roles",
- "tags": [
- "admin"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Users list returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "users"
- ],
- "properties": {
- "users": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "BBCodes returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
}
+ }
}
+ }
}
+ }
}
+ }
}
- },
- "/ocs/v2.php/apps/forum/api/admin/settings": {
- "get": {
- "operationId": "admin-get-settings",
- "summary": "Get general forum settings",
- "tags": [
- "admin"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Settings returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "admin-update-settings",
- "summary": "Update general forum settings",
- "tags": [
- "admin"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Forum title"
- },
- "subtitle": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Forum subtitle"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Settings updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/bbcodes": {
- "get": {
- "operationId": "bb_code-index",
- "summary": "Get all BBCodes (excludes builtin codes)",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "BBCodes returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "bb_code-create",
- "summary": "Create a new BBCode",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "tag",
- "replacement",
- "example"
- ],
- "properties": {
- "tag": {
- "type": "string",
- "description": "BBCode tag name"
- },
- "replacement": {
- "type": "string",
- "description": "Replacement pattern"
- },
- "example": {
- "type": "string",
- "description": "Example usage"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Optional description"
- },
- "enabled": {
- "type": "boolean",
- "default": true,
- "description": "Whether BBCode is enabled"
- },
- "parseInner": {
- "type": "boolean",
- "default": true,
- "description": "Whether to parse inner BBCode tags"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "BBCode created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/bbcodes/enabled": {
- "get": {
- "operationId": "bb_code-enabled",
- "summary": "Get enabled BBCodes",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Enabled BBCodes returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/bbcodes/builtin": {
- "get": {
- "operationId": "bb_code-builtin",
- "summary": "Get builtin BBCodes (for help dialog)",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Builtin BBCodes returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/bbcodes/{id}": {
- "get": {
- "operationId": "bb_code-show",
- "summary": "Get a single BBCode",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "BBCode ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "BBCode returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "bb_code-update",
- "summary": "Update a BBCode",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "tag": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "BBCode tag name"
- },
- "replacement": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Replacement pattern"
- },
- "example": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Example usage"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Description"
- },
- "enabled": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Whether BBCode is enabled"
- },
- "parseInner": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Whether to parse inner BBCode tags"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "BBCode ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "BBCode updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "bb_code-destroy",
- "summary": "Delete a BBCode",
- "tags": [
- "bb_code"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "BBCode ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "BBCode deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/headers": {
- "get": {
- "operationId": "cat_header-index",
- "summary": "Get all category headers",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category headers returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "cat_header-create",
- "summary": "Create a new category header",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "type": "string",
- "description": "Category header name"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category header description"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64",
- "default": 0,
- "description": "Sort order"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Category header created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/headers/{id}": {
- "get": {
- "operationId": "cat_header-show",
- "summary": "Get a single category header",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category header ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category header returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "cat_header-update",
- "summary": "Update a category header",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category header name"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category header description"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64",
- "nullable": true,
- "default": null,
- "description": "Sort order"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category header ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category header updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "cat_header-destroy",
- "summary": "Delete a category header",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category header ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "migrateToHeaderId",
- "in": "query",
- "description": "Header ID to migrate categories to (null to delete categories)",
- "schema": {
- "type": "integer",
- "format": "int64",
- "nullable": true,
- "default": null
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category header deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- },
- "categoriesAffected": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/headers/reorder": {
- "post": {
- "operationId": "cat_header-reorder",
- "summary": "Reorder category headers",
- "tags": [
- "cat_header"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "headers"
- ],
- "properties": {
- "headers": {
- "type": "array",
- "description": "Array of headers with new sort orders",
- "items": {
- "type": "object",
- "required": [
- "id",
- "sortOrder"
- ],
- "properties": {
- "id": {
- "type": "integer",
- "format": "int64"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Headers reordered successfully",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories": {
- "get": {
- "operationId": "category-index",
- "summary": "Get all category headers with nested categories",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category headers with nested categories returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "category-create",
- "summary": "Create a new category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "headerId",
- "name",
- "slug"
- ],
- "properties": {
- "headerId": {
- "type": "integer",
- "format": "int64",
- "description": "Category header ID"
- },
- "name": {
- "type": "string",
- "description": "Category name"
- },
- "slug": {
- "type": "string",
- "description": "Category slug"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category description"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64",
- "default": 0,
- "description": "Sort order"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Category created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/headers/{headerId}/categories": {
- "get": {
- "operationId": "category-by-header",
- "summary": "Get categories by header ID",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "headerId",
- "in": "path",
- "description": "Category header ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Categories returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/{id}": {
- "get": {
- "operationId": "category-show",
- "summary": "Get a single category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "category-update",
- "summary": "Update a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category name"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category description"
- },
- "slug": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Category slug"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64",
- "nullable": true,
- "default": null,
- "description": "Sort order"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "category-destroy",
- "summary": "Delete a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "migrateToCategoryId",
- "in": "query",
- "description": "Category ID to migrate threads to (null to soft-delete threads)",
- "schema": {
- "type": "integer",
- "format": "int64",
- "nullable": true,
- "default": null
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- },
- "threadsAffected": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/slug/{slug}": {
- "get": {
- "operationId": "category-by-slug",
- "summary": "Get a category by slug",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "slug",
- "in": "path",
- "description": "Category slug",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Category returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/{id}/thread-count": {
- "get": {
- "operationId": "category-get-thread-count",
- "summary": "Get thread count for a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread count returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "count"
- ],
- "properties": {
- "count": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/{id}/permissions/{permission}": {
- "get": {
- "operationId": "category-check-permission",
- "summary": "Check if current user has a specific permission on a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "permission",
- "in": "path",
- "description": "Permission name (canView, canPost, canReply, canModerate)",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Permission check result",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "hasPermission"
- ],
- "properties": {
- "hasPermission": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/{id}/permissions": {
- "get": {
- "operationId": "category-get-permissions",
- "summary": "Get permissions for a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Permissions returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "category-update-permissions",
- "summary": "Update permissions for a category",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "permissions"
- ],
- "properties": {
- "permissions": {
- "type": "array",
- "description": "Permissions array",
- "items": {
- "type": "object",
- "required": [
- "roleId",
- "canView",
- "canModerate"
- ],
- "properties": {
- "roleId": {
- "type": "integer",
- "format": "int64"
- },
- "canView": {
- "type": "boolean"
- },
- "canModerate": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Permissions updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/reorder": {
- "post": {
- "operationId": "category-reorder",
- "summary": "Reorder categories",
- "tags": [
- "category"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "categories"
- ],
- "properties": {
- "categories": {
- "type": "array",
- "description": "Array of categories with new sort orders",
- "items": {
- "type": "object",
- "required": [
- "id",
- "sortOrder"
- ],
- "properties": {
- "id": {
- "type": "integer",
- "format": "int64"
- },
- "sortOrder": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Categories reordered successfully",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/users": {
- "get": {
- "operationId": "forum_user-index",
- "summary": "Get all user statistics",
- "tags": [
- "forum_user"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "User statistics returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "forum_user-create",
- "summary": "Create user stats Note: This is typically not needed as stats are auto-created on first post",
- "tags": [
- "forum_user"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "userId"
- ],
- "properties": {
- "userId": {
- "type": "string",
- "description": "Nextcloud user ID"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "User stats created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/users/{userId}": {
- "get": {
- "operationId": "forum_user-show",
- "summary": "Get user statistics by Nextcloud user ID Special case: use \"me\" to get current user stats",
- "tags": [
- "forum_user"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "userId",
- "in": "path",
- "description": "Nextcloud user ID or \"me\" for current user",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "User stats returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "404": {
- "description": "User has no stats (hasn't posted yet)",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "error"
- ],
- "properties": {
- "error": {
- "type": "string"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "User not authenticated (when using \"me\")",
- "content": {
- "application/json": {
- "schema": {
- "anyOf": [
- {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "error"
- ],
- "properties": {
- "error": {
- "type": "string"
- }
- }
- }
- }
- }
- }
- },
- {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- ]
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/{threadId}/posts": {
- "get": {
- "operationId": "post-by-thread",
- "summary": "Get posts by thread",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "threadId",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "limit",
- "in": "query",
- "description": "Maximum number of posts to return",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 50
- }
- },
- {
- "name": "offset",
- "in": "query",
- "description": "Offset for pagination",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 0
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Posts returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/users/{authorId}/posts": {
- "get": {
- "operationId": "post-by-author",
- "summary": "Get posts by author",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "authorId",
- "in": "path",
- "description": "Author user ID",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "limit",
- "in": "query",
- "description": "Maximum number of posts to return",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 50
- }
- },
- {
- "name": "offset",
- "in": "query",
- "description": "Offset for pagination",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 0
- }
- },
- {
- "name": "excludeFirstPosts",
- "in": "query",
- "description": "Whether to exclude first posts (1 or 0)",
- "schema": {
- "type": "string",
- "default": "0"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Posts returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/posts/{id}": {
- "get": {
- "operationId": "post-show",
- "summary": "Get a single post",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Post ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Post returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "post-update",
- "summary": "Update a post",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "content": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Post content"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Post ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Post updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "post-destroy",
- "summary": "Delete a post (soft delete)",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Post ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Post deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/posts/slug/{slug}": {
- "get": {
- "operationId": "post-by-slug",
- "summary": "Get a post by slug",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "slug",
- "in": "path",
- "description": "Post slug",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Post returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/posts": {
- "post": {
- "operationId": "post-create",
- "summary": "Create a new post",
- "tags": [
- "post"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "threadId",
- "content"
- ],
- "properties": {
- "threadId": {
- "type": "integer",
- "format": "int64",
- "description": "Thread ID"
- },
- "content": {
- "type": "string",
- "description": "Post content"
- },
- "slug": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Post slug (auto-generated if not provided)"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Post created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/posts/{postId}/reactions": {
- "get": {
- "operationId": "reaction-by-post",
- "summary": "Get reactions by post",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "postId",
- "in": "path",
- "description": "Post ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Reactions returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/reactions/by-posts": {
- "post": {
- "operationId": "reaction-by-posts",
- "summary": "Get reactions for multiple posts (for performance)",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "postIds"
- ],
- "properties": {
- "postIds": {
- "type": "array",
- "description": "Array of post IDs",
- "items": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Reactions returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/reactions/{id}": {
- "get": {
- "operationId": "reaction-show",
- "summary": "Get a single reaction",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Reaction ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Reaction returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "reaction-destroy",
- "summary": "Delete a reaction",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Reaction ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Reaction deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/reactions": {
- "post": {
- "operationId": "reaction-create",
- "summary": "Create a new reaction",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "postId",
- "reactionType"
- ],
- "properties": {
- "postId": {
- "type": "integer",
- "format": "int64",
- "description": "Post ID"
- },
- "reactionType": {
- "type": "string",
- "description": "Type of reaction"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Reaction created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/reactions/toggle": {
- "post": {
- "operationId": "reaction-toggle",
- "summary": "Toggle a reaction (add if not exists, remove if exists)",
- "tags": [
- "reaction"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "postId",
- "reactionType"
- ],
- "properties": {
- "postId": {
- "type": "integer",
- "format": "int64",
- "description": "Post ID"
- },
- "reactionType": {
- "type": "string",
- "description": "Type of reaction (emoji)"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Reaction toggled",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "action"
- ],
- "properties": {
- "action": {
- "type": "string"
- },
- "reaction": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/read-markers": {
- "get": {
- "operationId": "read_marker-index",
- "summary": "Get read markers for multiple threads",
- "tags": [
- "read_marker"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "threadIds",
- "in": "query",
- "description": "Array of thread IDs (comma-separated in query string)",
- "schema": {
- "type": "string",
- "default": ""
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Read markers returned (keyed by thread ID)",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object",
- "required": [
- "threadId",
- "lastReadPostId",
- "readAt"
- ],
- "properties": {
- "threadId": {
- "type": "integer",
- "format": "int64"
- },
- "lastReadPostId": {
- "type": "integer",
- "format": "int64"
- },
- "readAt": {
- "type": "integer",
- "format": "int64"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "read_marker-create",
- "summary": "Mark a thread as read",
- "tags": [
- "read_marker"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "threadId",
- "lastReadPostId"
- ],
- "properties": {
- "threadId": {
- "type": "integer",
- "format": "int64",
- "description": "Thread ID"
- },
- "lastReadPostId": {
- "type": "integer",
- "format": "int64",
- "description": "Last read post ID"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread marked as read",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/{threadId}/read-marker": {
- "get": {
- "operationId": "read_marker-show",
- "summary": "Get read marker for a specific thread",
- "tags": [
- "read_marker"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "threadId",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Read marker returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/read-markers/{id}": {
- "delete": {
- "operationId": "read_marker-destroy",
- "summary": "Delete a read marker",
- "tags": [
- "read_marker"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Read marker ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Read marker deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/roles": {
- "get": {
- "operationId": "role-index",
- "summary": "Get all roles",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Roles returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "role-create",
- "summary": "Create a new role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "type": "string",
- "description": "Role name"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Role description"
- },
- "canAccessAdminTools": {
- "type": "boolean",
- "default": false,
- "description": "Can access admin tools"
- },
- "canEditRoles": {
- "type": "boolean",
- "default": false,
- "description": "Can edit roles"
- },
- "canEditCategories": {
- "type": "boolean",
- "default": false,
- "description": "Can edit categories"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Role created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/roles/{id}": {
- "get": {
- "operationId": "role-show",
- "summary": "Get a single role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Role returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "role-update",
- "summary": "Update a role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Role name"
- },
- "description": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Role description"
- },
- "canAccessAdminTools": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Can access admin tools"
- },
- "canEditRoles": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Can edit roles"
- },
- "canEditCategories": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Can edit categories"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Role updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "role-destroy",
- "summary": "Delete a role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Role deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/roles/{id}/permissions": {
- "get": {
- "operationId": "role-get-permissions",
- "summary": "Get permissions for a role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Permissions returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "role-update-permissions",
- "summary": "Update permissions for a role",
- "tags": [
- "role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "permissions"
- ],
- "properties": {
- "permissions": {
- "type": "array",
- "description": "Permissions array",
- "items": {
- "type": "object",
- "required": [
- "categoryId",
- "canView",
- "canModerate"
- ],
- "properties": {
- "categoryId": {
- "type": "integer",
- "format": "int64"
- },
- "canView": {
- "type": "boolean"
- },
- "canModerate": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Permissions updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/search": {
- "get": {
- "operationId": "search-index",
- "summary": "Search forum threads and posts",
- "tags": [
- "search"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "q",
- "in": "query",
- "description": "Search query (supports quoted phrases, AND/OR operators, parentheses, -exclusions)",
- "schema": {
- "type": "string",
- "default": ""
- }
- },
- {
- "name": "searchThreads",
- "in": "query",
- "description": "Include threads in search (title + first post content)",
- "schema": {
- "type": "boolean",
- "default": true
- }
- },
- {
- "name": "searchPosts",
- "in": "query",
- "description": "Include reply posts in search",
- "schema": {
- "type": "boolean",
- "default": true
- }
- },
- {
- "name": "categoryId",
- "in": "query",
- "description": "Optional category ID filter",
- "schema": {
- "type": "integer",
- "format": "int64",
- "nullable": true,
- "default": null
- }
- },
- {
- "name": "limit",
- "in": "query",
- "description": "Maximum results per type",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 50
- }
- },
- {
- "name": "offset",
- "in": "query",
- "description": "Results offset per type",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 0
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Search results returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "threads",
- "posts",
- "threadCount",
- "postCount",
- "query"
- ],
- "properties": {
- "threads": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- },
- "posts": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- },
- "threadCount": {
- "type": "integer",
- "format": "int64"
- },
- "postCount": {
- "type": "integer",
- "format": "int64"
- },
- "query": {
- "type": "string"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads": {
- "get": {
- "operationId": "thread-index",
- "summary": "Get all threads",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Threads returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "post": {
- "operationId": "thread-create",
- "summary": "Create a new thread with initial post",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "categoryId",
- "title",
- "content"
- ],
- "properties": {
- "categoryId": {
- "type": "integer",
- "format": "int64",
- "description": "Category ID"
- },
- "title": {
- "type": "string",
- "description": "Thread title"
- },
- "content": {
- "type": "string",
- "description": "Initial post content"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Thread created",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/categories/{categoryId}/threads": {
- "get": {
- "operationId": "thread-by-category",
- "summary": "Get threads by category",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "categoryId",
- "in": "path",
- "description": "Category ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "limit",
- "in": "query",
- "description": "Maximum number of threads to return",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 50
- }
- },
- {
- "name": "offset",
- "in": "query",
- "description": "Offset for pagination",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 0
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Threads returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/users/{authorId}/threads": {
- "get": {
- "operationId": "thread-by-author",
- "summary": "Get threads by author",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "authorId",
- "in": "path",
- "description": "Author user ID",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "limit",
- "in": "query",
- "description": "Maximum number of threads to return",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 50
- }
- },
- {
- "name": "offset",
- "in": "query",
- "description": "Offset for pagination",
- "schema": {
- "type": "integer",
- "format": "int64",
- "default": 0
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Threads returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/{id}": {
- "get": {
- "operationId": "thread-show",
- "summary": "Get a single thread",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "incrementView",
- "in": "query",
- "description": "Whether to increment view count (1 or 0)",
- "schema": {
- "type": "string",
- "default": "1"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "put": {
- "operationId": "thread-update",
- "summary": "Update a thread",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": false,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string",
- "nullable": true,
- "default": null,
- "description": "Thread title"
- },
- "isLocked": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Whether the thread is locked"
- },
- "isPinned": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Whether the thread is pinned"
- },
- "isHidden": {
- "type": "boolean",
- "nullable": true,
- "default": null,
- "description": "Whether the thread is hidden"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "delete": {
- "operationId": "thread-destroy",
- "summary": "Delete a thread (soft delete)",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread deleted",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success",
- "categorySlug"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- },
- "categorySlug": {
- "type": "string"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/slug/{slug}": {
- "get": {
- "operationId": "thread-by-slug",
- "summary": "Get a thread by slug",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "slug",
- "in": "path",
- "description": "Thread slug",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "incrementView",
- "in": "query",
- "description": "Whether to increment view count (1 or 0)",
- "schema": {
- "type": "string",
- "default": "1"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/{id}/lock": {
- "put": {
- "operationId": "thread-set-locked",
- "summary": "Toggle thread lock status",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "locked"
- ],
- "properties": {
- "locked": {
- "type": "boolean",
- "description": "New lock status"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread lock status updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/threads/{id}/pin": {
- "put": {
- "operationId": "thread-set-pinned",
- "summary": "Toggle thread pin status",
- "tags": [
- "thread"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "pinned"
- ],
- "properties": {
- "pinned": {
- "type": "boolean",
- "description": "New pin status"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "Thread ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Thread pin status updated",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/users/{userId}/roles": {
- "get": {
- "operationId": "user_role-by-user",
- "summary": "Get roles for a user",
- "tags": [
- "user_role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "userId",
- "in": "path",
- "description": "Nextcloud user ID",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "User roles returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/roles/{roleId}/users": {
- "get": {
- "operationId": "user_role-by-role",
- "summary": "Get users with a specific role",
- "tags": [
- "user_role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "roleId",
- "in": "path",
- "description": "Role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "User roles returned",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "array",
- "items": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/user-roles": {
- "post": {
- "operationId": "user_role-create",
- "summary": "Assign a role to a user",
- "tags": [
- "user_role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "userId",
- "roleId"
- ],
- "properties": {
- "userId": {
- "type": "string",
- "description": "Nextcloud user ID"
- },
- "roleId": {
- "type": "integer",
- "format": "int64",
- "description": "Role ID"
- }
- }
- }
- }
- }
- },
- "parameters": [
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "201": {
- "description": "Role assigned to user",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "additionalProperties": {
- "type": "object"
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "/ocs/v2.php/apps/forum/api/user-roles/{id}": {
- "delete": {
- "operationId": "user_role-destroy",
- "summary": "Remove a role from a user",
- "tags": [
- "user_role"
- ],
- "security": [
- {
- "bearer_auth": []
- },
- {
- "basic_auth": []
- }
- ],
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "User role ID",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- },
- {
- "name": "OCS-APIRequest",
- "in": "header",
- "description": "Required to be true for the API request to pass",
- "required": true,
- "schema": {
- "type": "boolean",
- "default": true
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Role removed from user",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {
- "type": "object",
- "required": [
- "success"
- ],
- "properties": {
- "success": {
- "type": "boolean"
- }
- }
- }
- }
- }
- }
- }
- }
- }
- },
- "401": {
- "description": "Current user is not logged in",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "ocs"
- ],
- "properties": {
- "ocs": {
- "type": "object",
- "required": [
- "meta",
- "data"
- ],
- "properties": {
- "meta": {
- "$ref": "#/components/schemas/OCSMeta"
- },
- "data": {}
- }
- }
- }
- }
- }
- }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
}
+ }
}
+ }
}
+ }
}
+ },
+ "post": {
+ "operationId": "bb_code-create",
+ "summary": "Create a new BBCode",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["tag", "replacement", "example"],
+ "properties": {
+ "tag": {
+ "type": "string",
+ "description": "BBCode tag name"
+ },
+ "replacement": {
+ "type": "string",
+ "description": "Replacement pattern"
+ },
+ "example": {
+ "type": "string",
+ "description": "Example usage"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Optional description"
+ },
+ "enabled": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether BBCode is enabled"
+ },
+ "parseInner": {
+ "type": "boolean",
+ "default": true,
+ "description": "Whether to parse inner BBCode tags"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "BBCode created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
},
- "tags": [
- {
- "name": "forum_user",
- "description": "Controller for user statistics Note: User stats are automatically created on first post/thread"
+ "/ocs/v2.php/apps/forum/api/bbcodes/enabled": {
+ "get": {
+ "operationId": "bb_code-enabled",
+ "summary": "Get enabled BBCodes",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Enabled BBCodes returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
- ]
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/bbcodes/builtin": {
+ "get": {
+ "operationId": "bb_code-builtin",
+ "summary": "Get builtin BBCodes (for help dialog)",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Builtin BBCodes returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/bbcodes/{id}": {
+ "get": {
+ "operationId": "bb_code-show",
+ "summary": "Get a single BBCode",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "BBCode ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "BBCode returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "bb_code-update",
+ "summary": "Update a BBCode",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "tag": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "BBCode tag name"
+ },
+ "replacement": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Replacement pattern"
+ },
+ "example": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Example usage"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Description"
+ },
+ "enabled": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Whether BBCode is enabled"
+ },
+ "parseInner": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Whether to parse inner BBCode tags"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "BBCode ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "BBCode updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "bb_code-destroy",
+ "summary": "Delete a BBCode",
+ "tags": ["bb_code"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "BBCode ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "BBCode deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/headers": {
+ "get": {
+ "operationId": "cat_header-index",
+ "summary": "Get all category headers",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category headers returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "cat_header-create",
+ "summary": "Create a new category header",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Category header name"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category header description"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0,
+ "description": "Sort order"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Category header created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/headers/{id}": {
+ "get": {
+ "operationId": "cat_header-show",
+ "summary": "Get a single category header",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category header ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category header returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "cat_header-update",
+ "summary": "Update a category header",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category header name"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category header description"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "default": null,
+ "description": "Sort order"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category header ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category header updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "cat_header-destroy",
+ "summary": "Delete a category header",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category header ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "migrateToHeaderId",
+ "in": "query",
+ "description": "Header ID to migrate categories to (null to delete categories)",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "default": null
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category header deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ },
+ "categoriesAffected": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/headers/reorder": {
+ "post": {
+ "operationId": "cat_header-reorder",
+ "summary": "Reorder category headers",
+ "tags": ["cat_header"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["headers"],
+ "properties": {
+ "headers": {
+ "type": "array",
+ "description": "Array of headers with new sort orders",
+ "items": {
+ "type": "object",
+ "required": ["id", "sortOrder"],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Headers reordered successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories": {
+ "get": {
+ "operationId": "category-index",
+ "summary": "Get all category headers with nested categories",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category headers with nested categories returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "category-create",
+ "summary": "Create a new category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["headerId", "name", "slug"],
+ "properties": {
+ "headerId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Category header ID"
+ },
+ "name": {
+ "type": "string",
+ "description": "Category name"
+ },
+ "slug": {
+ "type": "string",
+ "description": "Category slug"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category description"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0,
+ "description": "Sort order"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Category created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/headers/{headerId}/categories": {
+ "get": {
+ "operationId": "category-by-header",
+ "summary": "Get categories by header ID",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "headerId",
+ "in": "path",
+ "description": "Category header ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Categories returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/{id}": {
+ "get": {
+ "operationId": "category-show",
+ "summary": "Get a single category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "category-update",
+ "summary": "Update a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category name"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category description"
+ },
+ "slug": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Category slug"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "default": null,
+ "description": "Sort order"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "category-destroy",
+ "summary": "Delete a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "migrateToCategoryId",
+ "in": "query",
+ "description": "Category ID to migrate threads to (null to soft-delete threads)",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "default": null
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ },
+ "threadsAffected": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/slug/{slug}": {
+ "get": {
+ "operationId": "category-by-slug",
+ "summary": "Get a category by slug",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "description": "Category slug",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Category returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/{id}/thread-count": {
+ "get": {
+ "operationId": "category-get-thread-count",
+ "summary": "Get thread count for a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread count returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["count"],
+ "properties": {
+ "count": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/{id}/permissions/{permission}": {
+ "get": {
+ "operationId": "category-check-permission",
+ "summary": "Check if current user has a specific permission on a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "permission",
+ "in": "path",
+ "description": "Permission name (canView, canPost, canReply, canModerate)",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Permission check result",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["hasPermission"],
+ "properties": {
+ "hasPermission": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/{id}/permissions": {
+ "get": {
+ "operationId": "category-get-permissions",
+ "summary": "Get permissions for a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Permissions returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "category-update-permissions",
+ "summary": "Update permissions for a category",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["permissions"],
+ "properties": {
+ "permissions": {
+ "type": "array",
+ "description": "Permissions array",
+ "items": {
+ "type": "object",
+ "required": ["roleId", "canView", "canModerate"],
+ "properties": {
+ "roleId": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "canView": {
+ "type": "boolean"
+ },
+ "canModerate": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Permissions updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/reorder": {
+ "post": {
+ "operationId": "category-reorder",
+ "summary": "Reorder categories",
+ "tags": ["category"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["categories"],
+ "properties": {
+ "categories": {
+ "type": "array",
+ "description": "Array of categories with new sort orders",
+ "items": {
+ "type": "object",
+ "required": ["id", "sortOrder"],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "sortOrder": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Categories reordered successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/users": {
+ "get": {
+ "operationId": "forum_user-index",
+ "summary": "Get all user statistics",
+ "tags": ["forum_user"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User statistics returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "forum_user-create",
+ "summary": "Create user stats Note: This is typically not needed as stats are auto-created on first post",
+ "tags": ["forum_user"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["userId"],
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Nextcloud user ID"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "User stats created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/users/{userId}": {
+ "get": {
+ "operationId": "forum_user-show",
+ "summary": "Get user statistics by Nextcloud user ID Special case: use \"me\" to get current user stats",
+ "tags": ["forum_user"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "userId",
+ "in": "path",
+ "description": "Nextcloud user ID or \"me\" for current user",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User stats returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "User has no stats (hasn't posted yet)",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["error"],
+ "properties": {
+ "error": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "User not authenticated (when using \"me\")",
+ "content": {
+ "application/json": {
+ "schema": {
+ "anyOf": [
+ {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["error"],
+ "properties": {
+ "error": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{threadId}/posts": {
+ "get": {
+ "operationId": "post-by-thread",
+ "summary": "Get posts by thread",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadId",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Maximum number of posts to return",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 50
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "description": "Offset for pagination",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Posts returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/users/{authorId}/posts": {
+ "get": {
+ "operationId": "post-by-author",
+ "summary": "Get posts by author",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "authorId",
+ "in": "path",
+ "description": "Author user ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Maximum number of posts to return",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 50
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "description": "Offset for pagination",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0
+ }
+ },
+ {
+ "name": "excludeFirstPosts",
+ "in": "query",
+ "description": "Whether to exclude first posts (1 or 0)",
+ "schema": {
+ "type": "string",
+ "default": "0"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Posts returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/posts/{id}": {
+ "get": {
+ "operationId": "post-show",
+ "summary": "Get a single post",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Post ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Post returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "post-update",
+ "summary": "Update a post",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Post content"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Post ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Post updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "post-destroy",
+ "summary": "Delete a post (soft delete)",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Post ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Post deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/posts/slug/{slug}": {
+ "get": {
+ "operationId": "post-by-slug",
+ "summary": "Get a post by slug",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "description": "Post slug",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Post returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/posts": {
+ "post": {
+ "operationId": "post-create",
+ "summary": "Create a new post",
+ "tags": ["post"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["threadId", "content"],
+ "properties": {
+ "threadId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Thread ID"
+ },
+ "content": {
+ "type": "string",
+ "description": "Post content"
+ },
+ "slug": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Post slug (auto-generated if not provided)"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Post created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/posts/{postId}/reactions": {
+ "get": {
+ "operationId": "reaction-by-post",
+ "summary": "Get reactions by post",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "postId",
+ "in": "path",
+ "description": "Post ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reactions returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/reactions/by-posts": {
+ "post": {
+ "operationId": "reaction-by-posts",
+ "summary": "Get reactions for multiple posts (for performance)",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["postIds"],
+ "properties": {
+ "postIds": {
+ "type": "array",
+ "description": "Array of post IDs",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reactions returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/reactions/{id}": {
+ "get": {
+ "operationId": "reaction-show",
+ "summary": "Get a single reaction",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Reaction ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reaction returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "reaction-destroy",
+ "summary": "Delete a reaction",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Reaction ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reaction deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/reactions": {
+ "post": {
+ "operationId": "reaction-create",
+ "summary": "Create a new reaction",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["postId", "reactionType"],
+ "properties": {
+ "postId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Post ID"
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "Type of reaction"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Reaction created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/reactions/toggle": {
+ "post": {
+ "operationId": "reaction-toggle",
+ "summary": "Toggle a reaction (add if not exists, remove if exists)",
+ "tags": ["reaction"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["postId", "reactionType"],
+ "properties": {
+ "postId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Post ID"
+ },
+ "reactionType": {
+ "type": "string",
+ "description": "Type of reaction (emoji)"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Reaction toggled",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["action"],
+ "properties": {
+ "action": {
+ "type": "string"
+ },
+ "reaction": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/read-markers": {
+ "get": {
+ "operationId": "read_marker-index",
+ "summary": "Get read markers for multiple threads",
+ "tags": ["read_marker"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadIds",
+ "in": "query",
+ "description": "Array of thread IDs (comma-separated in query string)",
+ "schema": {
+ "type": "string",
+ "default": ""
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Read markers returned (keyed by thread ID)",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object",
+ "required": ["threadId", "lastReadPostId", "readAt"],
+ "properties": {
+ "threadId": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "lastReadPostId": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "readAt": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "read_marker-create",
+ "summary": "Mark a thread as read",
+ "tags": ["read_marker"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["threadId", "lastReadPostId"],
+ "properties": {
+ "threadId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Thread ID"
+ },
+ "lastReadPostId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Last read post ID"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread marked as read",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{threadId}/read-marker": {
+ "get": {
+ "operationId": "read_marker-show",
+ "summary": "Get read marker for a specific thread",
+ "tags": ["read_marker"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadId",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Read marker returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/read-markers/{id}": {
+ "delete": {
+ "operationId": "read_marker-destroy",
+ "summary": "Delete a read marker",
+ "tags": ["read_marker"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Read marker ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Read marker deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/roles": {
+ "get": {
+ "operationId": "role-index",
+ "summary": "Get all roles",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Roles returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "role-create",
+ "summary": "Create a new role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Role name"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Role description"
+ },
+ "canAccessAdminTools": {
+ "type": "boolean",
+ "default": false,
+ "description": "Can access admin tools"
+ },
+ "canEditRoles": {
+ "type": "boolean",
+ "default": false,
+ "description": "Can edit roles"
+ },
+ "canEditCategories": {
+ "type": "boolean",
+ "default": false,
+ "description": "Can edit categories"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Role created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/roles/{id}": {
+ "get": {
+ "operationId": "role-show",
+ "summary": "Get a single role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Role returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "role-update",
+ "summary": "Update a role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Role name"
+ },
+ "description": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Role description"
+ },
+ "canAccessAdminTools": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Can access admin tools"
+ },
+ "canEditRoles": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Can edit roles"
+ },
+ "canEditCategories": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Can edit categories"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Role updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "role-destroy",
+ "summary": "Delete a role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Role deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/roles/{id}/permissions": {
+ "get": {
+ "operationId": "role-get-permissions",
+ "summary": "Get permissions for a role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Permissions returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "role-update-permissions",
+ "summary": "Update permissions for a role",
+ "tags": ["role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["permissions"],
+ "properties": {
+ "permissions": {
+ "type": "array",
+ "description": "Permissions array",
+ "items": {
+ "type": "object",
+ "required": ["categoryId", "canView", "canModerate"],
+ "properties": {
+ "categoryId": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "canView": {
+ "type": "boolean"
+ },
+ "canModerate": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Permissions updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/search": {
+ "get": {
+ "operationId": "search-index",
+ "summary": "Search forum threads and posts",
+ "tags": ["search"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "q",
+ "in": "query",
+ "description": "Search query (supports quoted phrases, AND/OR operators, parentheses, -exclusions)",
+ "schema": {
+ "type": "string",
+ "default": ""
+ }
+ },
+ {
+ "name": "searchThreads",
+ "in": "query",
+ "description": "Include threads in search (title + first post content)",
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ },
+ {
+ "name": "searchPosts",
+ "in": "query",
+ "description": "Include reply posts in search",
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ },
+ {
+ "name": "categoryId",
+ "in": "query",
+ "description": "Optional category ID filter",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "nullable": true,
+ "default": null
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Maximum results per type",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 50
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "description": "Results offset per type",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Search results returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["threads", "posts", "threadCount", "postCount", "query"],
+ "properties": {
+ "threads": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ },
+ "posts": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ },
+ "threadCount": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "postCount": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "query": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads": {
+ "get": {
+ "operationId": "thread-index",
+ "summary": "Get all threads",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Threads returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "thread-create",
+ "summary": "Create a new thread with initial post",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["categoryId", "title", "content"],
+ "properties": {
+ "categoryId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Category ID"
+ },
+ "title": {
+ "type": "string",
+ "description": "Thread title"
+ },
+ "content": {
+ "type": "string",
+ "description": "Initial post content"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Thread created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/categories/{categoryId}/threads": {
+ "get": {
+ "operationId": "thread-by-category",
+ "summary": "Get threads by category",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "categoryId",
+ "in": "path",
+ "description": "Category ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Maximum number of threads to return",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 50
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "description": "Offset for pagination",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Threads returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/users/{authorId}/threads": {
+ "get": {
+ "operationId": "thread-by-author",
+ "summary": "Get threads by author",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "authorId",
+ "in": "path",
+ "description": "Author user ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Maximum number of threads to return",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 50
+ }
+ },
+ {
+ "name": "offset",
+ "in": "query",
+ "description": "Offset for pagination",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 0
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Threads returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{id}": {
+ "get": {
+ "operationId": "thread-show",
+ "summary": "Get a single thread",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "incrementView",
+ "in": "query",
+ "description": "Whether to increment view count (1 or 0)",
+ "schema": {
+ "type": "string",
+ "default": "1"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "thread-update",
+ "summary": "Update a thread",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string",
+ "nullable": true,
+ "default": null,
+ "description": "Thread title"
+ },
+ "isLocked": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Whether the thread is locked"
+ },
+ "isPinned": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Whether the thread is pinned"
+ },
+ "isHidden": {
+ "type": "boolean",
+ "nullable": true,
+ "default": null,
+ "description": "Whether the thread is hidden"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "thread-destroy",
+ "summary": "Delete a thread (soft delete)",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success", "categorySlug"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ },
+ "categorySlug": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/slug/{slug}": {
+ "get": {
+ "operationId": "thread-by-slug",
+ "summary": "Get a thread by slug",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "slug",
+ "in": "path",
+ "description": "Thread slug",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "incrementView",
+ "in": "query",
+ "description": "Whether to increment view count (1 or 0)",
+ "schema": {
+ "type": "string",
+ "default": "1"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{id}/lock": {
+ "put": {
+ "operationId": "thread-set-locked",
+ "summary": "Toggle thread lock status",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["locked"],
+ "properties": {
+ "locked": {
+ "type": "boolean",
+ "description": "New lock status"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread lock status updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{id}/pin": {
+ "put": {
+ "operationId": "thread-set-pinned",
+ "summary": "Toggle thread pin status",
+ "tags": ["thread"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["pinned"],
+ "properties": {
+ "pinned": {
+ "type": "boolean",
+ "description": "New pin status"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread pin status updated",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/threads/{threadId}/subscribe": {
+ "post": {
+ "operationId": "thread_subscription-subscribe",
+ "summary": "Subscribe current user to a thread to receive notifications",
+ "tags": ["thread_subscription"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadId",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User subscribed to thread",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "operationId": "thread_subscription-unsubscribe",
+ "summary": "Unsubscribe current user from a thread",
+ "tags": ["thread_subscription"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadId",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User unsubscribed from thread",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "operationId": "thread_subscription-is-subscribed",
+ "summary": "Check if current user is subscribed to a thread",
+ "tags": ["thread_subscription"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "threadId",
+ "in": "path",
+ "description": "Thread ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Subscription status returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/thread-subscriptions": {
+ "get": {
+ "operationId": "thread_subscription-get-user-subscriptions",
+ "summary": "Get all threads the current user is subscribed to",
+ "tags": ["thread_subscription"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Thread subscriptions returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/users/{userId}/roles": {
+ "get": {
+ "operationId": "user_role-by-user",
+ "summary": "Get roles for a user",
+ "tags": ["user_role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "userId",
+ "in": "path",
+ "description": "Nextcloud user ID",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User roles returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/roles/{roleId}/users": {
+ "get": {
+ "operationId": "user_role-by-role",
+ "summary": "Get users with a specific role",
+ "tags": ["user_role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "roleId",
+ "in": "path",
+ "description": "Role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "User roles returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/user-roles": {
+ "post": {
+ "operationId": "user_role-create",
+ "summary": "Assign a role to a user",
+ "tags": ["user_role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["userId", "roleId"],
+ "properties": {
+ "userId": {
+ "type": "string",
+ "description": "Nextcloud user ID"
+ },
+ "roleId": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Role ID"
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "Role assigned to user",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/forum/api/user-roles/{id}": {
+ "delete": {
+ "operationId": "user_role-destroy",
+ "summary": "Remove a role from a user",
+ "tags": ["user_role"],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "User role ID",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Role removed from user",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": ["success"],
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Current user is not logged in",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": ["ocs"],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": ["meta", "data"],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "forum_user",
+ "description": "Controller for user statistics Note: User stats are automatically created on first post/thread"
+ }
+ ]
}
diff --git a/src/types/models.ts b/src/types/models.ts
index 8efe852..35e3963 100644
--- a/src/types/models.ts
+++ b/src/types/models.ts
@@ -44,6 +44,7 @@ export interface Thread {
authorIsDeleted?: boolean
categorySlug?: string | null
categoryName?: string | null
+ isSubscribed?: boolean
}
export interface Post {
diff --git a/src/views/ThreadView.vue b/src/views/ThreadView.vue
index 1069d94..afa0058 100644
--- a/src/views/ThreadView.vue
+++ b/src/views/ThreadView.vue
@@ -12,6 +12,19 @@
+
+
+
+
+ {{ thread.isSubscribed ? strings.subscribed : strings.subscribe }}
+
+
+
import { defineComponent } from 'vue'
import NcButton from '@nextcloud/vue/components/NcButton'
+import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcDateTime from '@nextcloud/vue/components/NcDateTime'
@@ -193,6 +207,7 @@ import PinOffIcon from '@icons/PinOff.vue'
import LockIcon from '@icons/Lock.vue'
import LockOpenIcon from '@icons/LockOpen.vue'
import EyeIcon from '@icons/Eye.vue'
+import BellIcon from '@icons/Bell.vue'
import ArrowLeftIcon from '@icons/ArrowLeft.vue'
import RefreshIcon from '@icons/Refresh.vue'
import ReplyIcon from '@icons/Reply.vue'
@@ -207,6 +222,7 @@ export default defineComponent({
name: 'ThreadView',
components: {
NcButton,
+ NcCheckboxRadioSwitch,
NcEmptyContent,
NcLoadingIcon,
NcDateTime,
@@ -218,6 +234,7 @@ export default defineComponent({
LockIcon,
LockOpenIcon,
EyeIcon,
+ BellIcon,
ArrowLeftIcon,
RefreshIcon,
ReplyIcon,
@@ -268,6 +285,10 @@ export default defineComponent({
threadUnlocked: t('forum', 'Thread unlocked'),
threadPinned: t('forum', 'Thread pinned'),
threadUnpinned: t('forum', 'Thread unpinned'),
+ subscribe: t('forum', 'Subscribe to thread'),
+ subscribed: t('forum', 'Subscribed'),
+ threadSubscribed: t('forum', 'Subscribed to thread'),
+ threadUnsubscribed: t('forum', 'Unsubscribed from thread'),
},
}
},
@@ -610,6 +631,29 @@ export default defineComponent({
}
},
+ async handleToggleSubscription(newValue: boolean): Promise {
+ if (!this.thread) return
+
+ try {
+ if (newValue) {
+ // Subscribe to thread
+ await ocs.post(`/threads/${this.thread.id}/subscribe`)
+ this.thread.isSubscribed = true
+ showSuccess(this.strings.threadSubscribed)
+ } else {
+ // Unsubscribe from thread
+ await ocs.delete(`/threads/${this.thread.id}/subscribe`)
+ this.thread.isSubscribed = false
+ showSuccess(this.strings.threadUnsubscribed)
+ }
+ } catch (e) {
+ console.error('Failed to toggle thread subscription', e)
+ showError(t('forum', 'Failed to update subscription'))
+ // Revert the state on error
+ this.thread.isSubscribed = !newValue
+ }
+ },
+
scrollToPostFromHash(): void {
// Check if there's a hash in the URL like #post-123
const hash = window.location.hash || this.$route.hash
@@ -686,6 +730,12 @@ export default defineComponent({
.thread-view {
margin-bottom: 3rem;
+ .icon-label {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ }
+
.muted {
color: var(--color-text-maxcontrast);
opacity: 0.7;
@@ -820,6 +870,7 @@ export default defineComponent({
background-color: var(--color-primary-element-light);
box-shadow: 0 0 0 4px var(--color-primary-element-light);
}
+
100% {
background-color: transparent;
box-shadow: none;